mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Auto merge of #101986 - WaffleLapkin:move_lint_note_to_the_bottom, r=estebank
Move lint level source explanation to the bottom So, uhhhhh r? `@estebank` ## User-facing change "note: `#[warn(...)]` on by default" and such are moved to the bottom of the diagnostic: ```diff - = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> + = note: `#[warn(unsupported_calling_conventions)]` on by default ``` Why warning is enabled is the least important thing, so it shouldn't be the first note the user reads, IMO. ## Developer-facing change `struct_span_lint` and similar methods have a different signature. Before: `..., impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>)` After: `..., impl Into<DiagnosticMessage>, impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>) -> &'b mut DiagnosticBuilder<'a, ()>` The reason for this is that `struct_span_lint` needs to edit the diagnostic _after_ `decorate` closure is called. This also makes lint code a little bit nicer in my opinion. Another option is to use `impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) -> DiagnosticBuilder<'a, ()>` altough I don't _really_ see reasons to do `let lint = lint.build(message)` everywhere. ## Subtle problem By moving the message outside of the closure (that may not be called if the lint is disabled) `format!(...)` is executed earlier, possibly formatting `Ty` which may call a query that trims paths that crashes the compiler if there were no warnings... I don't think it's that big of a deal, considering that we move from `format!(...)` to `fluent` (which is lazy by-default) anyway, however this required adding a workaround which is unfortunate. ## P.S. I'm sorry, I do not how to make this PR smaller/easier to review. Changes to the lint API affect SO MUCH 😢
This commit is contained in:
commit
744e397d88
@ -233,10 +233,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
|
|||||||
rustc_session::lint::builtin::CONST_ERR,
|
rustc_session::lint::builtin::CONST_ERR,
|
||||||
hir_id,
|
hir_id,
|
||||||
tcx.span,
|
tcx.span,
|
||||||
|
message,
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut lint = lint.build(message);
|
finish(lint, Some(err_msg));
|
||||||
finish(&mut lint, Some(err_msg));
|
lint
|
||||||
lint.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ErrorHandled::Linted
|
ErrorHandled::Linted
|
||||||
|
@ -358,6 +358,17 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A workaround for "good path" ICEs when formatting types in disables lints.
|
||||||
|
///
|
||||||
|
/// Delays formatting until `.into(): DiagnosticMessage` is used.
|
||||||
|
pub struct DelayDm<F>(pub F);
|
||||||
|
|
||||||
|
impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagnosticMessage {
|
||||||
|
fn from(DelayDm(f): DelayDm<F>) -> Self {
|
||||||
|
DiagnosticMessage::from(f())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
|
/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
|
||||||
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
|
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
|
||||||
/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be
|
/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::snippet::Style;
|
use crate::snippet::Style;
|
||||||
use crate::{
|
use crate::{
|
||||||
CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan,
|
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
|
||||||
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
||||||
};
|
};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
@ -209,7 +209,12 @@ pub trait AddToDiagnostic {
|
|||||||
#[rustc_diagnostic_item = "DecorateLint"]
|
#[rustc_diagnostic_item = "DecorateLint"]
|
||||||
pub trait DecorateLint<'a, G: EmissionGuarantee> {
|
pub trait DecorateLint<'a, G: EmissionGuarantee> {
|
||||||
/// Decorate and emit a lint.
|
/// Decorate and emit a lint.
|
||||||
fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>);
|
fn decorate_lint<'b>(
|
||||||
|
self,
|
||||||
|
diag: &'b mut DiagnosticBuilder<'a, G>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, G>;
|
||||||
|
|
||||||
|
fn msg(&self) -> DiagnosticMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -642,27 +642,3 @@ macro_rules! struct_span_err {
|
|||||||
macro_rules! error_code {
|
macro_rules! error_code {
|
||||||
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
|
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper around a `DiagnosticBuilder` for creating lints.
|
|
||||||
pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
|
|
||||||
|
|
||||||
impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
|
|
||||||
#[rustc_lint_diagnostics]
|
|
||||||
/// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
|
|
||||||
pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> {
|
|
||||||
self.0.set_primary_message(msg);
|
|
||||||
self.0.set_is_lint();
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
|
|
||||||
pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
|
|
||||||
LintDiagnosticBuilder(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
|
|
||||||
pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
|
|
||||||
LintDiagnosticBuilder(self.0.forget_guarantee())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,7 @@ use rustc_data_structures::stable_hasher::StableHasher;
|
|||||||
use rustc_data_structures::sync::{self, Lock, Lrc};
|
use rustc_data_structures::sync::{self, Lock, Lrc};
|
||||||
use rustc_data_structures::AtomicRef;
|
use rustc_data_structures::AtomicRef;
|
||||||
pub use rustc_error_messages::{
|
pub use rustc_error_messages::{
|
||||||
fallback_fluent_bundle, fluent, fluent_bundle, DiagnosticMessage, FluentBundle,
|
fallback_fluent_bundle, fluent, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
|
||||||
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
|
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
|
||||||
DEFAULT_LOCALE_RESOURCES,
|
DEFAULT_LOCALE_RESOURCES,
|
||||||
};
|
};
|
||||||
@ -374,7 +374,7 @@ pub use diagnostic::{
|
|||||||
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
|
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
|
||||||
DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
||||||
};
|
};
|
||||||
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder};
|
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
|
||||||
use std::backtrace::Backtrace;
|
use std::backtrace::Backtrace;
|
||||||
|
|
||||||
/// A handler deals with errors and other compiler output.
|
/// A handler deals with errors and other compiler output.
|
||||||
|
@ -649,9 +649,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
LATE_BOUND_LIFETIME_ARGUMENTS,
|
LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||||
args.args[0].hir_id(),
|
args.args[0].hir_id(),
|
||||||
multispan,
|
multispan,
|
||||||
|lint| {
|
msg,
|
||||||
lint.build(msg).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2010,30 +2010,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
|
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
|
||||||
|
|
||||||
if let Some(variant_def_id) = variant_resolution {
|
if let Some(variant_def_id) = variant_resolution {
|
||||||
tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
let mut err = lint.build("ambiguous associated item");
|
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||||
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
hir_ref_id,
|
||||||
let note_msg = format!(
|
span,
|
||||||
"`{}` could{} refer to the {} defined here",
|
"ambiguous associated item",
|
||||||
assoc_ident,
|
|lint| {
|
||||||
also,
|
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
||||||
kind.descr(def_id)
|
let note_msg = format!(
|
||||||
|
"`{}` could{} refer to the {} defined here",
|
||||||
|
assoc_ident,
|
||||||
|
also,
|
||||||
|
kind.descr(def_id)
|
||||||
|
);
|
||||||
|
lint.span_note(tcx.def_span(def_id), ¬e_msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
could_refer_to(DefKind::Variant, variant_def_id, "");
|
||||||
|
could_refer_to(kind, item.def_id, " also");
|
||||||
|
|
||||||
|
lint.span_suggestion(
|
||||||
|
span,
|
||||||
|
"use fully-qualified syntax",
|
||||||
|
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.span_note(tcx.def_span(def_id), ¬e_msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
could_refer_to(DefKind::Variant, variant_def_id, "");
|
lint
|
||||||
could_refer_to(kind, item.def_id, " also");
|
},
|
||||||
|
);
|
||||||
err.span_suggestion(
|
|
||||||
span,
|
|
||||||
"use fully-qualified syntax",
|
|
||||||
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
|
|
||||||
err.emit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Ok((ty, kind, item.def_id))
|
Ok((ty, kind, item.def_id))
|
||||||
}
|
}
|
||||||
@ -3079,15 +3084,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
BARE_TRAIT_OBJECTS,
|
BARE_TRAIT_OBJECTS,
|
||||||
self_ty.hir_id,
|
self_ty.hir_id,
|
||||||
self_ty.span,
|
self_ty.span,
|
||||||
|
msg,
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut diag = lint.build(msg);
|
lint.multipart_suggestion_verbose(
|
||||||
diag.multipart_suggestion_verbose(
|
|
||||||
"use `dyn`",
|
"use `dyn`",
|
||||||
sugg,
|
sugg,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
|
self.maybe_lint_blanket_trait_impl(&self_ty, lint);
|
||||||
diag.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ use super::FnCtxt;
|
|||||||
use crate::hir::def_id::DefId;
|
use crate::hir::def_id::DefId;
|
||||||
use crate::type_error_struct;
|
use crate::type_error_struct;
|
||||||
use hir::def_id::LOCAL_CRATE;
|
use hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode};
|
use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
@ -754,19 +754,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
("", lint::builtin::TRIVIAL_CASTS)
|
("", lint::builtin::TRIVIAL_CASTS)
|
||||||
};
|
};
|
||||||
fcx.tcx.struct_span_lint_hir(lint, self.expr.hir_id, self.span, |err| {
|
fcx.tcx.struct_span_lint_hir(
|
||||||
err.build(&format!(
|
lint,
|
||||||
"trivial {}cast: `{}` as `{}`",
|
self.expr.hir_id,
|
||||||
adjective,
|
self.span,
|
||||||
fcx.ty_to_string(t_expr),
|
DelayDm(|| {
|
||||||
fcx.ty_to_string(t_cast)
|
format!(
|
||||||
))
|
"trivial {}cast: `{}` as `{}`",
|
||||||
.help(&format!(
|
adjective,
|
||||||
"cast can be replaced by coercion; this might \
|
fcx.ty_to_string(t_expr),
|
||||||
require {type_asc_or}a temporary variable"
|
fcx.ty_to_string(t_cast)
|
||||||
))
|
)
|
||||||
.emit();
|
}),
|
||||||
});
|
|lint| {
|
||||||
|
lint.help(format!(
|
||||||
|
"cast can be replaced by coercion; this might \
|
||||||
|
require {type_asc_or}a temporary variable"
|
||||||
|
))
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(fcx), level = "debug")]
|
#[instrument(skip(fcx), level = "debug")]
|
||||||
@ -1074,12 +1080,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
lint::builtin::CENUM_IMPL_DROP_CAST,
|
lint::builtin::CENUM_IMPL_DROP_CAST,
|
||||||
self.expr.hir_id,
|
self.expr.hir_id,
|
||||||
self.span,
|
self.span,
|
||||||
|err| {
|
DelayDm(|| format!(
|
||||||
err.build(&format!(
|
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
|
||||||
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
|
self.expr_ty, self.cast_ty
|
||||||
self.expr_ty, self.cast_ty
|
)),
|
||||||
))
|
|lint| {
|
||||||
.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1090,12 +1096,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
lint::builtin::LOSSY_PROVENANCE_CASTS,
|
lint::builtin::LOSSY_PROVENANCE_CASTS,
|
||||||
self.expr.hir_id,
|
self.expr.hir_id,
|
||||||
self.span,
|
self.span,
|
||||||
|err| {
|
DelayDm(|| format!(
|
||||||
let mut err = err.build(&format!(
|
|
||||||
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
|
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
|
||||||
self.expr_ty, self.cast_ty
|
self.expr_ty, self.cast_ty
|
||||||
));
|
)),
|
||||||
|
|lint| {
|
||||||
let msg = "use `.addr()` to obtain the address of a pointer";
|
let msg = "use `.addr()` to obtain the address of a pointer";
|
||||||
|
|
||||||
let expr_prec = self.expr.precedence().order();
|
let expr_prec = self.expr.precedence().order();
|
||||||
@ -1114,9 +1119,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
(cast_span, format!(").addr(){scalar_cast}")),
|
(cast_span, format!(").addr(){scalar_cast}")),
|
||||||
];
|
];
|
||||||
|
|
||||||
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||||
} else {
|
} else {
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
cast_span,
|
cast_span,
|
||||||
msg,
|
msg,
|
||||||
format!(".addr(){scalar_cast}"),
|
format!(".addr(){scalar_cast}"),
|
||||||
@ -1124,12 +1129,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
err.help(
|
lint.help(
|
||||||
"if you can't comply with strict provenance and need to expose the pointer \
|
"if you can't comply with strict provenance and need to expose the pointer \
|
||||||
provenance you can use `.expose_addr()` instead"
|
provenance you can use `.expose_addr()` instead"
|
||||||
);
|
);
|
||||||
|
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1139,24 +1144,24 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
lint::builtin::FUZZY_PROVENANCE_CASTS,
|
lint::builtin::FUZZY_PROVENANCE_CASTS,
|
||||||
self.expr.hir_id,
|
self.expr.hir_id,
|
||||||
self.span,
|
self.span,
|
||||||
|err| {
|
DelayDm(|| format!(
|
||||||
let mut err = err.build(&format!(
|
"strict provenance disallows casting integer `{}` to pointer `{}`",
|
||||||
"strict provenance disallows casting integer `{}` to pointer `{}`",
|
self.expr_ty, self.cast_ty
|
||||||
self.expr_ty, self.cast_ty
|
)),
|
||||||
));
|
|lint| {
|
||||||
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
|
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
|
||||||
let suggestions = vec![
|
let suggestions = vec![
|
||||||
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
|
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
|
||||||
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
|
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
|
||||||
];
|
];
|
||||||
|
|
||||||
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||||
err.help(
|
lint.help(
|
||||||
"if you can't comply with strict provenance and don't have a pointer with \
|
"if you can't comply with strict provenance and don't have a pointer with \
|
||||||
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
|
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
|
||||||
);
|
);
|
||||||
|
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,13 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
lint.build("use of calling convention not supported on this target").emit();
|
UNSUPPORTED_CALLING_CONVENTIONS,
|
||||||
});
|
hir_id,
|
||||||
|
span,
|
||||||
|
"use of calling convention not supported on this target",
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,10 +514,10 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
|||||||
UNINHABITED_STATIC,
|
UNINHABITED_STATIC,
|
||||||
tcx.hir().local_def_id_to_hir_id(def_id),
|
tcx.hir().local_def_id_to_hir_id(def_id),
|
||||||
span,
|
span,
|
||||||
|
"static of uninhabited type",
|
||||||
|lint| {
|
|lint| {
|
||||||
lint.build("static of uninhabited type")
|
lint
|
||||||
.note("uninhabited statics cannot be initialized, and any access would be an immediate error")
|
.note("uninhabited statics cannot be initialized, and any access would be an immediate error")
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1437,6 +1441,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
|
|||||||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
|
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
|
||||||
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
|
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
|
||||||
span,
|
span,
|
||||||
|
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
|
||||||
|lint| {
|
|lint| {
|
||||||
let note = if non_exhaustive {
|
let note = if non_exhaustive {
|
||||||
"is marked with `#[non_exhaustive]`"
|
"is marked with `#[non_exhaustive]`"
|
||||||
@ -1444,10 +1449,9 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
|
|||||||
"contains private fields"
|
"contains private fields"
|
||||||
};
|
};
|
||||||
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
|
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
|
||||||
lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types")
|
lint
|
||||||
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
|
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
|
||||||
and makes it not a breaking change to become non-zero-sized in the future."))
|
and makes it not a breaking change to become non-zero-sized in the future."))
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -58,17 +58,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
|
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
|
||||||
|
|
||||||
self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
|
let msg = format!("unreachable {}", kind);
|
||||||
let msg = format!("unreachable {}", kind);
|
self.tcx().struct_span_lint_hir(
|
||||||
lint.build(&msg)
|
lint::builtin::UNREACHABLE_CODE,
|
||||||
.span_label(span, &msg)
|
id,
|
||||||
.span_label(
|
span,
|
||||||
|
&msg,
|
||||||
|
|lint| {
|
||||||
|
lint.span_label(span, &msg).span_label(
|
||||||
orig_span,
|
orig_span,
|
||||||
custom_note
|
custom_note
|
||||||
.unwrap_or("any code following this expression is unreachable"),
|
.unwrap_or("any code following this expression is unreachable"),
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use self::drop_ranges::DropRanges;
|
use self::drop_ranges::DropRanges;
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::pluralize;
|
use rustc_errors::{pluralize, DelayDm};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
@ -610,33 +610,33 @@ fn check_must_not_suspend_def(
|
|||||||
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
|
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
|
||||||
hir_id,
|
hir_id,
|
||||||
data.source_span,
|
data.source_span,
|
||||||
|lint| {
|
DelayDm(|| {
|
||||||
let msg = format!(
|
format!(
|
||||||
"{}`{}`{} held across a suspend point, but should not be",
|
"{}`{}`{} held across a suspend point, but should not be",
|
||||||
data.descr_pre,
|
data.descr_pre,
|
||||||
tcx.def_path_str(def_id),
|
tcx.def_path_str(def_id),
|
||||||
data.descr_post,
|
data.descr_post,
|
||||||
);
|
)
|
||||||
let mut err = lint.build(&msg);
|
}),
|
||||||
|
|lint| {
|
||||||
// add span pointing to the offending yield/await
|
// add span pointing to the offending yield/await
|
||||||
err.span_label(data.yield_span, "the value is held across this suspend point");
|
lint.span_label(data.yield_span, "the value is held across this suspend point");
|
||||||
|
|
||||||
// Add optional reason note
|
// Add optional reason note
|
||||||
if let Some(note) = attr.value_str() {
|
if let Some(note) = attr.value_str() {
|
||||||
// FIXME(guswynn): consider formatting this better
|
// FIXME(guswynn): consider formatting this better
|
||||||
err.span_note(data.source_span, note.as_str());
|
lint.span_note(data.source_span, note.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add some quick suggestions on what to do
|
// Add some quick suggestions on what to do
|
||||||
// FIXME: can `drop` work as a suggestion here as well?
|
// FIXME: can `drop` work as a suggestion here as well?
|
||||||
err.span_help(
|
lint.span_help(
|
||||||
data.source_span,
|
data.source_span,
|
||||||
"consider using a block (`{ ... }`) \
|
"consider using a block (`{ ... }`) \
|
||||||
to shrink the value's scope, ending before the suspend point",
|
to shrink the value's scope, ending before the suspend point",
|
||||||
);
|
);
|
||||||
|
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -328,17 +328,16 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||||||
lint::builtin::ASM_SUB_REGISTER,
|
lint::builtin::ASM_SUB_REGISTER,
|
||||||
expr.hir_id,
|
expr.hir_id,
|
||||||
spans,
|
spans,
|
||||||
|
"formatting may not be suitable for sub-register argument",
|
||||||
|lint| {
|
|lint| {
|
||||||
let msg = "formatting may not be suitable for sub-register argument";
|
lint.span_label(expr.span, "for this argument");
|
||||||
let mut err = lint.build(msg);
|
lint.help(&format!(
|
||||||
err.span_label(expr.span, "for this argument");
|
|
||||||
err.help(&format!(
|
|
||||||
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
|
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
|
||||||
));
|
));
|
||||||
err.help(&format!(
|
lint.help(&format!(
|
||||||
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
|
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
|
||||||
));
|
));
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
prelude_or_array_lint,
|
prelude_or_array_lint,
|
||||||
self_expr.hir_id,
|
self_expr.hir_id,
|
||||||
self_expr.span,
|
self_expr.span,
|
||||||
|
format!("trait method `{}` will become ambiguous in Rust 2021", segment.ident.name),
|
||||||
|lint| {
|
|lint| {
|
||||||
let sp = self_expr.span;
|
let sp = self_expr.span;
|
||||||
|
|
||||||
let mut lint = lint.build(&format!(
|
|
||||||
"trait method `{}` will become ambiguous in Rust 2021",
|
|
||||||
segment.ident.name
|
|
||||||
));
|
|
||||||
|
|
||||||
let derefs = "*".repeat(pick.autoderefs);
|
let derefs = "*".repeat(pick.autoderefs);
|
||||||
|
|
||||||
let autoref = match pick.autoref_or_ptr_adjustment {
|
let autoref = match pick.autoref_or_ptr_adjustment {
|
||||||
@ -133,7 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
lint.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -143,6 +139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
prelude_or_array_lint,
|
prelude_or_array_lint,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
call_expr.span,
|
call_expr.span,
|
||||||
|
format!("trait method `{}` will become ambiguous in Rust 2021", segment.ident.name),
|
||||||
|lint| {
|
|lint| {
|
||||||
let sp = call_expr.span;
|
let sp = call_expr.span;
|
||||||
let trait_name = self.trait_path_or_bare_name(
|
let trait_name = self.trait_path_or_bare_name(
|
||||||
@ -151,11 +148,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
pick.item.container_id(self.tcx),
|
pick.item.container_id(self.tcx),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut lint = lint.build(&format!(
|
|
||||||
"trait method `{}` will become ambiguous in Rust 2021",
|
|
||||||
segment.ident.name
|
|
||||||
));
|
|
||||||
|
|
||||||
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
|
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
|
||||||
if precise {
|
if precise {
|
||||||
let args = args
|
let args = args
|
||||||
@ -202,7 +194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
lint.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -257,15 +249,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
|
self.tcx.struct_span_lint_hir(
|
||||||
// "type" refers to either a type or, more likely, a trait from which
|
RUST_2021_PRELUDE_COLLISIONS,
|
||||||
// the associated function or method is from.
|
expr_id,
|
||||||
let container_id = pick.item.container_id(self.tcx);
|
span,
|
||||||
let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
|
format!(
|
||||||
let trait_generics = self.tcx.generics_of(container_id);
|
"trait-associated function `{}` will become ambiguous in Rust 2021",
|
||||||
|
method_name.name
|
||||||
|
),
|
||||||
|
|lint| {
|
||||||
|
// "type" refers to either a type or, more likely, a trait from which
|
||||||
|
// the associated function or method is from.
|
||||||
|
let container_id = pick.item.container_id(self.tcx);
|
||||||
|
let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
|
||||||
|
let trait_generics = self.tcx.generics_of(container_id);
|
||||||
|
|
||||||
let trait_name =
|
let trait_name = if trait_generics.params.len() <= trait_generics.has_self as usize
|
||||||
if trait_generics.params.len() <= trait_generics.has_self as usize {
|
{
|
||||||
trait_path
|
trait_path
|
||||||
} else {
|
} else {
|
||||||
let counts = trait_generics.own_counts();
|
let counts = trait_generics.own_counts();
|
||||||
@ -282,44 +282,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lint = lint.build(&format!(
|
let mut self_ty_name = self_ty_span
|
||||||
"trait-associated function `{}` will become ambiguous in Rust 2021",
|
.find_ancestor_inside(span)
|
||||||
method_name.name
|
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
||||||
));
|
.unwrap_or_else(|| self_ty.to_string());
|
||||||
|
|
||||||
let mut self_ty_name = self_ty_span
|
// Get the number of generics the self type has (if an Adt) unless we can determine that
|
||||||
.find_ancestor_inside(span)
|
// the user has written the self type with generics already which we (naively) do by looking
|
||||||
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
|
// for a "<" in `self_ty_name`.
|
||||||
.unwrap_or_else(|| self_ty.to_string());
|
if !self_ty_name.contains('<') {
|
||||||
|
if let Adt(def, _) = self_ty.kind() {
|
||||||
// Get the number of generics the self type has (if an Adt) unless we can determine that
|
let generics = self.tcx.generics_of(def.did());
|
||||||
// the user has written the self type with generics already which we (naively) do by looking
|
if !generics.params.is_empty() {
|
||||||
// for a "<" in `self_ty_name`.
|
let counts = generics.own_counts();
|
||||||
if !self_ty_name.contains('<') {
|
self_ty_name += &format!(
|
||||||
if let Adt(def, _) = self_ty.kind() {
|
"<{}>",
|
||||||
let generics = self.tcx.generics_of(def.did());
|
std::iter::repeat("'_")
|
||||||
if !generics.params.is_empty() {
|
.take(counts.lifetimes)
|
||||||
let counts = generics.own_counts();
|
.chain(
|
||||||
self_ty_name += &format!(
|
std::iter::repeat("_").take(counts.types + counts.consts)
|
||||||
"<{}>",
|
)
|
||||||
std::iter::repeat("'_")
|
.collect::<Vec<_>>()
|
||||||
.take(counts.lifetimes)
|
.join(", ")
|
||||||
.chain(std::iter::repeat("_").take(counts.types + counts.consts))
|
);
|
||||||
.collect::<Vec<_>>()
|
}
|
||||||
.join(", ")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
lint.span_suggestion(
|
||||||
lint.span_suggestion(
|
span,
|
||||||
span,
|
"disambiguate the associated function",
|
||||||
"disambiguate the associated function",
|
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
|
||||||
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
lint.emit();
|
lint
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_path_or_bare_name(
|
fn trait_path_or_bare_name(
|
||||||
|
@ -409,9 +409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||||
scope_expr_id,
|
scope_expr_id,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
"type annotations needed",
|
||||||
lint.build("type annotations needed").emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1358,24 +1357,24 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
stable_pick: &Pick<'_>,
|
stable_pick: &Pick<'_>,
|
||||||
unstable_candidates: &[(Candidate<'tcx>, Symbol)],
|
unstable_candidates: &[(Candidate<'tcx>, Symbol)],
|
||||||
) {
|
) {
|
||||||
|
let def_kind = stable_pick.item.kind.as_def_kind();
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::UNSTABLE_NAME_COLLISIONS,
|
lint::builtin::UNSTABLE_NAME_COLLISIONS,
|
||||||
self.scope_expr_id,
|
self.scope_expr_id,
|
||||||
self.span,
|
self.span,
|
||||||
|
format!(
|
||||||
|
"{} {} with this name may be added to the standard library in the future",
|
||||||
|
def_kind.article(),
|
||||||
|
def_kind.descr(stable_pick.item.def_id),
|
||||||
|
),
|
||||||
|lint| {
|
|lint| {
|
||||||
let def_kind = stable_pick.item.kind.as_def_kind();
|
|
||||||
let mut diag = lint.build(&format!(
|
|
||||||
"{} {} with this name may be added to the standard library in the future",
|
|
||||||
def_kind.article(),
|
|
||||||
def_kind.descr(stable_pick.item.def_id),
|
|
||||||
));
|
|
||||||
match (stable_pick.item.kind, stable_pick.item.container) {
|
match (stable_pick.item.kind, stable_pick.item.container) {
|
||||||
(ty::AssocKind::Fn, _) => {
|
(ty::AssocKind::Fn, _) => {
|
||||||
// FIXME: This should be a `span_suggestion` instead of `help`
|
// FIXME: This should be a `span_suggestion` instead of `help`
|
||||||
// However `self.span` only
|
// However `self.span` only
|
||||||
// highlights the method name, so we can't use it. Also consider reusing
|
// highlights the method name, so we can't use it. Also consider reusing
|
||||||
// the code from `report_method_error()`.
|
// the code from `report_method_error()`.
|
||||||
diag.help(&format!(
|
lint.help(&format!(
|
||||||
"call with fully qualified syntax `{}(...)` to keep using the current \
|
"call with fully qualified syntax `{}(...)` to keep using the current \
|
||||||
method",
|
method",
|
||||||
self.tcx.def_path_str(stable_pick.item.def_id),
|
self.tcx.def_path_str(stable_pick.item.def_id),
|
||||||
@ -1383,7 +1382,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
||||||
let def_id = stable_pick.item.container_id(self.tcx);
|
let def_id = stable_pick.item.container_id(self.tcx);
|
||||||
diag.span_suggestion(
|
lint.span_suggestion(
|
||||||
self.span,
|
self.span,
|
||||||
"use the fully qualified path to the associated const",
|
"use the fully qualified path to the associated const",
|
||||||
format!(
|
format!(
|
||||||
@ -1399,7 +1398,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
if self.tcx.sess.is_nightly_build() {
|
if self.tcx.sess.is_nightly_build() {
|
||||||
for (candidate, feature) in unstable_candidates {
|
for (candidate, feature) in unstable_candidates {
|
||||||
diag.help(&format!(
|
lint.help(&format!(
|
||||||
"add `#![feature({})]` to the crate attributes to enable `{}`",
|
"add `#![feature({})]` to the crate attributes to enable `{}`",
|
||||||
feature,
|
feature,
|
||||||
self.tcx.def_path_str(candidate.item.def_id),
|
self.tcx.def_path_str(candidate.item.def_id),
|
||||||
@ -1407,7 +1406,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diag.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1790,10 +1790,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
|
&unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
|
self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
|
||||||
let mut lint = build.build("some fields are not explicitly listed");
|
|
||||||
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
|
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
|
||||||
|
|
||||||
lint.help(
|
lint.help(
|
||||||
"ensure that all fields are mentioned explicitly by adding the suggested fields",
|
"ensure that all fields are mentioned explicitly by adding the suggested fields",
|
||||||
);
|
);
|
||||||
@ -1801,7 +1799,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
"the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
"the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
||||||
ty,
|
ty,
|
||||||
));
|
));
|
||||||
lint.emit();
|
|
||||||
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,10 +749,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
|
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
|
||||||
closure_hir_id,
|
closure_hir_id,
|
||||||
closure_head_span,
|
closure_head_span,
|
||||||
|
reasons.migration_message(),
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut diagnostics_builder = lint.build(
|
|
||||||
&reasons.migration_message(),
|
|
||||||
);
|
|
||||||
for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
|
for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
|
||||||
// Labels all the usage of the captured variable and why they are responsible
|
// Labels all the usage of the captured variable and why they are responsible
|
||||||
// for migration being needed
|
// for migration being needed
|
||||||
@ -760,13 +758,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
match &lint_note.captures_info {
|
match &lint_note.captures_info {
|
||||||
UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
|
UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
|
||||||
let cause_span = self.tcx.hir().span(*capture_expr_id);
|
let cause_span = self.tcx.hir().span(*capture_expr_id);
|
||||||
diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
|
lint.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
|
||||||
self.tcx.hir().name(*var_hir_id),
|
self.tcx.hir().name(*var_hir_id),
|
||||||
captured_name,
|
captured_name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
UpvarMigrationInfo::CapturingNothing { use_span } => {
|
UpvarMigrationInfo::CapturingNothing { use_span } => {
|
||||||
diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
|
lint.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
|
||||||
self.tcx.hir().name(*var_hir_id),
|
self.tcx.hir().name(*var_hir_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -781,13 +779,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
match &lint_note.captures_info {
|
match &lint_note.captures_info {
|
||||||
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
|
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
|
||||||
diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
|
lint.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
|
||||||
self.tcx.hir().name(*var_hir_id),
|
self.tcx.hir().name(*var_hir_id),
|
||||||
captured_name,
|
captured_name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
|
UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
|
||||||
diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
|
lint.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
|
||||||
v = self.tcx.hir().name(*var_hir_id),
|
v = self.tcx.hir().name(*var_hir_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -800,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
match &lint_note.captures_info {
|
match &lint_note.captures_info {
|
||||||
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
|
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
|
||||||
let var_name = self.tcx.hir().name(*var_hir_id);
|
let var_name = self.tcx.hir().name(*var_hir_id);
|
||||||
diagnostics_builder.span_label(closure_head_span, format!("\
|
lint.span_label(closure_head_span, format!("\
|
||||||
in Rust 2018, this closure implements {missing_trait} \
|
in Rust 2018, this closure implements {missing_trait} \
|
||||||
as `{var_name}` implements {missing_trait}, but in Rust 2021, \
|
as `{var_name}` implements {missing_trait}, but in Rust 2021, \
|
||||||
this closure will no longer implement {missing_trait} \
|
this closure will no longer implement {missing_trait} \
|
||||||
@ -814,7 +812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
|
lint.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
|
||||||
|
|
||||||
let diagnostic_msg = format!(
|
let diagnostic_msg = format!(
|
||||||
"add a dummy let to cause {} to be fully captured",
|
"add a dummy let to cause {} to be fully captured",
|
||||||
@ -857,7 +855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// We take the indentation from the next non-empty line.
|
// We take the indentation from the next non-empty line.
|
||||||
let line2 = lines.find(|line| !line.is_empty()).unwrap_or_default();
|
let line2 = lines.find(|line| !line.is_empty()).unwrap_or_default();
|
||||||
let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
|
let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
|
||||||
diagnostics_builder.span_suggestion(
|
lint.span_suggestion(
|
||||||
closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(),
|
closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(),
|
||||||
&diagnostic_msg,
|
&diagnostic_msg,
|
||||||
format!("\n{indent}{migration_string};"),
|
format!("\n{indent}{migration_string};"),
|
||||||
@ -868,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// braces, but with more than just the opening
|
// braces, but with more than just the opening
|
||||||
// brace on the first line. We put the `let`
|
// brace on the first line. We put the `let`
|
||||||
// directly after the `{`.
|
// directly after the `{`.
|
||||||
diagnostics_builder.span_suggestion(
|
lint.span_suggestion(
|
||||||
closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(),
|
closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(),
|
||||||
&diagnostic_msg,
|
&diagnostic_msg,
|
||||||
format!(" {migration_string};"),
|
format!(" {migration_string};"),
|
||||||
@ -877,7 +875,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
// This is a closure without braces around the body.
|
// This is a closure without braces around the body.
|
||||||
// We add braces to add the `let` before the body.
|
// We add braces to add the `let` before the body.
|
||||||
diagnostics_builder.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
&diagnostic_msg,
|
&diagnostic_msg,
|
||||||
vec![
|
vec![
|
||||||
(closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")),
|
(closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")),
|
||||||
@ -887,7 +885,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
diagnostics_builder.span_suggestion(
|
lint.span_suggestion(
|
||||||
closure_span,
|
closure_span,
|
||||||
&diagnostic_msg,
|
&diagnostic_msg,
|
||||||
migration_string,
|
migration_string,
|
||||||
@ -895,7 +893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics_builder.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,18 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
|
let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
|
||||||
tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, |lint| {
|
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
|
||||||
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
|
format!("unused import: `{}`", snippet)
|
||||||
format!("unused import: `{}`", snippet)
|
} else {
|
||||||
} else {
|
"unused import".to_owned()
|
||||||
"unused import".to_owned()
|
};
|
||||||
};
|
tcx.struct_span_lint_hir(
|
||||||
lint.build(&msg).emit();
|
lint::builtin::UNUSED_IMPORTS,
|
||||||
});
|
item.hir_id(),
|
||||||
|
path.span,
|
||||||
|
msg,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unused_crates_lint(tcx);
|
unused_crates_lint(tcx);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//! crate or pertains to a type defined in this crate.
|
//! crate or pertains to a type defined in this crate.
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::{struct_span_err, DelayDm};
|
||||||
use rustc_errors::{Diagnostic, ErrorGuaranteed};
|
use rustc_errors::{Diagnostic, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
@ -412,30 +412,31 @@ fn lint_auto_trait_impl<'tcx>(
|
|||||||
lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
|
lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
|
||||||
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
||||||
tcx.def_span(impl_def_id),
|
tcx.def_span(impl_def_id),
|
||||||
|err| {
|
DelayDm(|| {
|
||||||
let item_span = tcx.def_span(self_type_did);
|
format!(
|
||||||
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
|
|
||||||
let mut err = err.build(&format!(
|
|
||||||
"cross-crate traits with a default impl, like `{}`, \
|
"cross-crate traits with a default impl, like `{}`, \
|
||||||
should not be specialized",
|
should not be specialized",
|
||||||
tcx.def_path_str(trait_ref.def_id),
|
tcx.def_path_str(trait_ref.def_id),
|
||||||
));
|
)
|
||||||
|
}),
|
||||||
|
|lint| {
|
||||||
|
let item_span = tcx.def_span(self_type_did);
|
||||||
|
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
|
||||||
match arg {
|
match arg {
|
||||||
ty::util::NotUniqueParam::DuplicateParam(arg) => {
|
ty::util::NotUniqueParam::DuplicateParam(arg) => {
|
||||||
err.note(&format!("`{}` is mentioned multiple times", arg));
|
lint.note(&format!("`{}` is mentioned multiple times", arg));
|
||||||
}
|
}
|
||||||
ty::util::NotUniqueParam::NotParam(arg) => {
|
ty::util::NotUniqueParam::NotParam(arg) => {
|
||||||
err.note(&format!("`{}` is not a generic parameter", arg));
|
lint.note(&format!("`{}` is not a generic parameter", arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.span_note(
|
lint.span_note(
|
||||||
item_span,
|
item_span,
|
||||||
&format!(
|
&format!(
|
||||||
"try using the same sequence of generic parameters as the {} definition",
|
"try using the same sequence of generic parameters as the {} definition",
|
||||||
self_descr,
|
self_descr,
|
||||||
),
|
),
|
||||||
);
|
)
|
||||||
err.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2067,11 +2067,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
|||||||
lint::builtin::INLINE_NO_SANITIZE,
|
lint::builtin::INLINE_NO_SANITIZE,
|
||||||
hir_id,
|
hir_id,
|
||||||
no_sanitize_span,
|
no_sanitize_span,
|
||||||
|lint| {
|
"`no_sanitize` will have no effect after inlining",
|
||||||
lint.build("`no_sanitize` will have no effect after inlining")
|
|lint| lint.span_note(inline_span, "inlining requested here"),
|
||||||
.span_note(inline_span, "inlining requested here")
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,9 +266,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||||||
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
||||||
param.hir_id,
|
param.hir_id,
|
||||||
param.span,
|
param.span,
|
||||||
|lint| {
|
TYPE_DEFAULT_NOT_ALLOWED,
|
||||||
lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Defaults::Deny => {
|
Defaults::Deny => {
|
||||||
|
@ -118,37 +118,41 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
|
|||||||
// to an array or to a slice.
|
// to an array or to a slice.
|
||||||
_ => bug!("array type coerced to something other than array or slice"),
|
_ => bug!("array type coerced to something other than array or slice"),
|
||||||
};
|
};
|
||||||
cx.struct_span_lint(ARRAY_INTO_ITER, call.ident.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut diag = lint.build(fluent::lint::array_into_iter);
|
ARRAY_INTO_ITER,
|
||||||
diag.set_arg("target", target);
|
call.ident.span,
|
||||||
diag.span_suggestion(
|
fluent::lint::array_into_iter,
|
||||||
call.ident.span,
|
|diag| {
|
||||||
fluent::lint::use_iter_suggestion,
|
diag.set_arg("target", target);
|
||||||
"iter",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
if self.for_expr_span == expr.span {
|
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
call.ident.span,
|
||||||
fluent::lint::remove_into_iter_suggestion,
|
fluent::lint::use_iter_suggestion,
|
||||||
"",
|
"iter",
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
} else if receiver_ty.is_array() {
|
if self.for_expr_span == expr.span {
|
||||||
diag.multipart_suggestion(
|
diag.span_suggestion(
|
||||||
fluent::lint::use_explicit_into_iter_suggestion,
|
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||||
vec![
|
fluent::lint::remove_into_iter_suggestion,
|
||||||
(expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
|
"",
|
||||||
(
|
Applicability::MaybeIncorrect,
|
||||||
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
);
|
||||||
")".into(),
|
} else if receiver_ty.is_array() {
|
||||||
),
|
diag.multipart_suggestion(
|
||||||
],
|
fluent::lint::use_explicit_into_iter_suggestion,
|
||||||
Applicability::MaybeIncorrect,
|
vec![
|
||||||
);
|
(expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
|
||||||
}
|
(
|
||||||
diag.emit();
|
receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||||
})
|
")".into(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
diag
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ use rustc_ast_pretty::pprust::{self, expr_to_string};
|
|||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
fluent, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
|
||||||
LintDiagnosticBuilder, MultiSpan,
|
DiagnosticStyledString, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
|
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -103,9 +103,12 @@ impl EarlyLintPass for WhileTrue {
|
|||||||
&& !lit.span.from_expansion()
|
&& !lit.span.from_expansion()
|
||||||
{
|
{
|
||||||
let condition_span = e.span.with_hi(cond.span.hi());
|
let condition_span = e.span.with_hi(cond.span.hi());
|
||||||
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_while_true)
|
WHILE_TRUE,
|
||||||
.span_suggestion_short(
|
condition_span,
|
||||||
|
fluent::lint::builtin_while_true,
|
||||||
|
|lint| {
|
||||||
|
lint.span_suggestion_short(
|
||||||
condition_span,
|
condition_span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
format!(
|
format!(
|
||||||
@ -117,8 +120,8 @@ impl EarlyLintPass for WhileTrue {
|
|||||||
),
|
),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,9 +157,12 @@ impl BoxPointers {
|
|||||||
for leaf in ty.walk() {
|
for leaf in ty.walk() {
|
||||||
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
|
||||||
if leaf_ty.is_box() {
|
if leaf_ty.is_box() {
|
||||||
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit();
|
BOX_POINTERS,
|
||||||
});
|
span,
|
||||||
|
fluent::lint::builtin_box_pointers,
|
||||||
|
|lint| lint.set_arg("ty", ty),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,19 +261,21 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|
|||||||
if cx.tcx.find_field_index(ident, &variant)
|
if cx.tcx.find_field_index(ident, &variant)
|
||||||
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let suggested_ident =
|
NON_SHORTHAND_FIELD_PATTERNS,
|
||||||
format!("{}{}", binding_annot.prefix_str(), ident);
|
fieldpat.span,
|
||||||
lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
|
fluent::lint::builtin_non_shorthand_field_patterns,
|
||||||
.set_arg("ident", ident.clone())
|
|lint| {
|
||||||
.span_suggestion(
|
let suggested_ident =
|
||||||
|
format!("{}{}", binding_annot.prefix_str(), ident);
|
||||||
|
lint.set_arg("ident", ident.clone()).span_suggestion(
|
||||||
fieldpat.span,
|
fieldpat.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
suggested_ident,
|
suggested_ident,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,14 +315,17 @@ impl UnsafeCode {
|
|||||||
&self,
|
&self,
|
||||||
cx: &EarlyContext<'_>,
|
cx: &EarlyContext<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
// This comes from a macro that has `#[allow_internal_unsafe]`.
|
// This comes from a macro that has `#[allow_internal_unsafe]`.
|
||||||
if span.allows_unsafe() {
|
if span.allows_unsafe() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(UNSAFE_CODE, span, decorate);
|
cx.struct_span_lint(UNSAFE_CODE, span, msg, decorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_overridden_symbol_name(
|
fn report_overridden_symbol_name(
|
||||||
@ -323,8 +334,8 @@ impl UnsafeCode {
|
|||||||
span: Span,
|
span: Span,
|
||||||
msg: DiagnosticMessage,
|
msg: DiagnosticMessage,
|
||||||
) {
|
) {
|
||||||
self.report_unsafe(cx, span, |lint| {
|
self.report_unsafe(cx, span, msg, |lint| {
|
||||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit();
|
lint.note(fluent::lint::builtin_overridden_symbol_name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,8 +345,8 @@ impl UnsafeCode {
|
|||||||
span: Span,
|
span: Span,
|
||||||
msg: DiagnosticMessage,
|
msg: DiagnosticMessage,
|
||||||
) {
|
) {
|
||||||
self.report_unsafe(cx, span, |lint| {
|
self.report_unsafe(cx, span, msg, |lint| {
|
||||||
lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit();
|
lint.note(fluent::lint::builtin_overridden_symbol_section)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,9 +354,12 @@ impl UnsafeCode {
|
|||||||
impl EarlyLintPass for UnsafeCode {
|
impl EarlyLintPass for UnsafeCode {
|
||||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||||
if attr.has_name(sym::allow_internal_unsafe) {
|
if attr.has_name(sym::allow_internal_unsafe) {
|
||||||
self.report_unsafe(cx, attr.span, |lint| {
|
self.report_unsafe(
|
||||||
lint.build(fluent::lint::builtin_allow_internal_unsafe).emit();
|
cx,
|
||||||
});
|
attr.span,
|
||||||
|
fluent::lint::builtin_allow_internal_unsafe,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,24 +367,20 @@ impl EarlyLintPass for UnsafeCode {
|
|||||||
if let ast::ExprKind::Block(ref blk, _) = e.kind {
|
if let ast::ExprKind::Block(ref blk, _) = e.kind {
|
||||||
// Don't warn about generated blocks; that'll just pollute the output.
|
// Don't warn about generated blocks; that'll just pollute the output.
|
||||||
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
|
||||||
self.report_unsafe(cx, blk.span, |lint| {
|
self.report_unsafe(cx, blk.span, fluent::lint::builtin_unsafe_block, |lint| lint);
|
||||||
lint.build(fluent::lint::builtin_unsafe_block).emit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
|
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => {
|
||||||
.report_unsafe(cx, it.span, |lint| {
|
self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_trait, |lint| lint)
|
||||||
lint.build(fluent::lint::builtin_unsafe_trait).emit();
|
}
|
||||||
}),
|
|
||||||
|
|
||||||
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
|
ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => {
|
||||||
.report_unsafe(cx, it.span, |lint| {
|
self.report_unsafe(cx, it.span, fluent::lint::builtin_unsafe_impl, |lint| lint)
|
||||||
lint.build(fluent::lint::builtin_unsafe_impl).emit();
|
}
|
||||||
}),
|
|
||||||
|
|
||||||
ast::ItemKind::Fn(..) => {
|
ast::ItemKind::Fn(..) => {
|
||||||
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
|
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
|
||||||
@ -463,9 +473,7 @@ impl EarlyLintPass for UnsafeCode {
|
|||||||
FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
|
FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
|
||||||
FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
|
FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
|
||||||
};
|
};
|
||||||
self.report_unsafe(cx, span, |lint| {
|
self.report_unsafe(cx, span, msg, |lint| lint);
|
||||||
lint.build(msg).emit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,12 +574,12 @@ impl MissingDoc {
|
|||||||
let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
|
let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
|
||||||
let has_doc = attrs.iter().any(has_doc);
|
let has_doc = attrs.iter().any(has_doc);
|
||||||
if !has_doc {
|
if !has_doc {
|
||||||
cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_missing_doc)
|
MISSING_DOCS,
|
||||||
.set_arg("article", article)
|
cx.tcx.def_span(def_id),
|
||||||
.set_arg("desc", desc)
|
fluent::lint::builtin_missing_doc,
|
||||||
.emit();
|
|lint| lint.set_arg("article", article).set_arg("desc", desc),
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -758,9 +766,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
|||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_missing_copy_impl).emit();
|
MISSING_COPY_IMPLEMENTATIONS,
|
||||||
})
|
item.span,
|
||||||
|
fluent::lint::builtin_missing_copy_impl,
|
||||||
|
|lint| lint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -834,11 +845,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) {
|
if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) {
|
||||||
cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_missing_debug_impl)
|
MISSING_DEBUG_IMPLEMENTATIONS,
|
||||||
.set_arg("debug", cx.tcx.def_path_str(debug))
|
item.span,
|
||||||
.emit();
|
fluent::lint::builtin_missing_debug_impl,
|
||||||
});
|
|lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -906,24 +918,26 @@ impl EarlyLintPass for AnonymousParameters {
|
|||||||
for arg in sig.decl.inputs.iter() {
|
for arg in sig.decl.inputs.iter() {
|
||||||
if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
|
if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
|
||||||
if ident.name == kw::Empty {
|
if ident.name == kw::Empty {
|
||||||
cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| {
|
let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
|
||||||
let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
|
|
||||||
|
|
||||||
let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
|
let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
|
||||||
(snip.as_str(), Applicability::MachineApplicable)
|
(snip.as_str(), Applicability::MachineApplicable)
|
||||||
} else {
|
} else {
|
||||||
("<type>", Applicability::HasPlaceholders)
|
("<type>", Applicability::HasPlaceholders)
|
||||||
};
|
};
|
||||||
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_anonymous_params)
|
ANONYMOUS_PARAMETERS,
|
||||||
.span_suggestion(
|
arg.pat.span,
|
||||||
|
fluent::lint::builtin_anonymous_params,
|
||||||
|
|lint| {
|
||||||
|
lint.span_suggestion(
|
||||||
arg.pat.span,
|
arg.pat.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
format!("_: {}", ty_snip),
|
format!("_: {}", ty_snip),
|
||||||
appl,
|
appl,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -958,38 +972,44 @@ impl EarlyLintPass for DeprecatedAttr {
|
|||||||
_,
|
_,
|
||||||
) = gate
|
) = gate
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
// FIXME(davidtwco) translatable deprecated attr
|
||||||
// FIXME(davidtwco) translatable deprecated attr
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_deprecated_attr_link)
|
DEPRECATED,
|
||||||
.set_arg("name", name)
|
attr.span,
|
||||||
.set_arg("reason", reason)
|
fluent::lint::builtin_deprecated_attr_link,
|
||||||
.set_arg("link", link)
|
|lint| {
|
||||||
.span_suggestion_short(
|
lint.set_arg("name", name)
|
||||||
attr.span,
|
.set_arg("reason", reason)
|
||||||
suggestion.map(|s| s.into()).unwrap_or(
|
.set_arg("link", link)
|
||||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
.span_suggestion_short(
|
||||||
),
|
attr.span,
|
||||||
"",
|
suggestion.map(|s| s.into()).unwrap_or(
|
||||||
Applicability::MachineApplicable,
|
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||||
)
|
),
|
||||||
.emit();
|
"",
|
||||||
});
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
|
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
|
||||||
cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_deprecated_attr_used)
|
DEPRECATED,
|
||||||
.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
|
attr.span,
|
||||||
.span_suggestion_short(
|
fluent::lint::builtin_deprecated_attr_used,
|
||||||
attr.span,
|
|lint| {
|
||||||
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
|
||||||
"",
|
.span_suggestion_short(
|
||||||
Applicability::MachineApplicable,
|
attr.span,
|
||||||
)
|
fluent::lint::builtin_deprecated_attr_default_suggestion,
|
||||||
.emit();
|
"",
|
||||||
});
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1016,20 +1036,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
|
|||||||
let span = sugared_span.take().unwrap_or(attr.span);
|
let span = sugared_span.take().unwrap_or(attr.span);
|
||||||
|
|
||||||
if is_doc_comment || attr.has_name(sym::doc) {
|
if is_doc_comment || attr.has_name(sym::doc) {
|
||||||
cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::builtin_unused_doc_comment);
|
UNUSED_DOC_COMMENTS,
|
||||||
err.set_arg("kind", node_kind);
|
span,
|
||||||
err.span_label(node_span, fluent::lint::label);
|
fluent::lint::builtin_unused_doc_comment,
|
||||||
match attr.kind {
|
|lint| {
|
||||||
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
|
lint.set_arg("kind", node_kind).span_label(node_span, fluent::lint::label).help(
|
||||||
err.help(fluent::lint::plain_help);
|
match attr.kind {
|
||||||
}
|
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
|
||||||
AttrKind::DocComment(CommentKind::Block, _) => {
|
fluent::lint::plain_help
|
||||||
err.help(fluent::lint::block_help);
|
}
|
||||||
}
|
AttrKind::DocComment(CommentKind::Block, _) => fluent::lint::block_help,
|
||||||
}
|
},
|
||||||
err.emit();
|
)
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,9 +1164,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
GenericParamKind::Lifetime { .. } => {}
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
||||||
cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_no_mangle_generic)
|
NO_MANGLE_GENERIC_ITEMS,
|
||||||
.span_suggestion_short(
|
span,
|
||||||
|
fluent::lint::builtin_no_mangle_generic,
|
||||||
|
|lint| {
|
||||||
|
lint.span_suggestion_short(
|
||||||
no_mangle_attr.span,
|
no_mangle_attr.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
"",
|
"",
|
||||||
@ -1153,8 +1177,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||||||
// fix may be to monomorphize source by hand
|
// fix may be to monomorphize source by hand
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1170,27 +1194,29 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
|||||||
if cx.sess().contains_name(attrs, sym::no_mangle) {
|
if cx.sess().contains_name(attrs, sym::no_mangle) {
|
||||||
// Const items do not refer to a particular location in memory, and therefore
|
// Const items do not refer to a particular location in memory, and therefore
|
||||||
// don't have anything to attach a symbol to
|
// don't have anything to attach a symbol to
|
||||||
cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::builtin_const_no_mangle);
|
NO_MANGLE_CONST_ITEMS,
|
||||||
|
it.span,
|
||||||
// account for "pub const" (#45562)
|
fluent::lint::builtin_const_no_mangle,
|
||||||
let start = cx
|
|lint| {
|
||||||
.tcx
|
// account for "pub const" (#45562)
|
||||||
.sess
|
let start = cx
|
||||||
.source_map()
|
.tcx
|
||||||
.span_to_snippet(it.span)
|
.sess
|
||||||
.map(|snippet| snippet.find("const").unwrap_or(0))
|
.source_map()
|
||||||
.unwrap_or(0) as u32;
|
.span_to_snippet(it.span)
|
||||||
// `const` is 5 chars
|
.map(|snippet| snippet.find("const").unwrap_or(0))
|
||||||
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
|
.unwrap_or(0) as u32;
|
||||||
err.span_suggestion(
|
// `const` is 5 chars
|
||||||
const_span,
|
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
|
||||||
fluent::lint::suggestion,
|
lint.span_suggestion(
|
||||||
"pub static",
|
const_span,
|
||||||
Applicability::MachineApplicable,
|
fluent::lint::suggestion,
|
||||||
);
|
"pub static",
|
||||||
err.emit();
|
Applicability::MachineApplicable,
|
||||||
});
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
|
hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
|
||||||
@ -1250,9 +1276,12 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
|||||||
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
|
||||||
{
|
{
|
||||||
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
|
||||||
cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_mutable_transmutes).emit();
|
MUTABLE_TRANSMUTES,
|
||||||
});
|
expr.span,
|
||||||
|
fluent::lint::builtin_mutable_transmutes,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1300,9 +1329,12 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
|||||||
if attr.has_name(sym::feature) {
|
if attr.has_name(sym::feature) {
|
||||||
if let Some(items) = attr.meta_item_list() {
|
if let Some(items) = attr.meta_item_list() {
|
||||||
for item in items {
|
for item in items {
|
||||||
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_unstable_features).emit();
|
UNSTABLE_FEATURES,
|
||||||
});
|
item.span(),
|
||||||
|
fluent::lint::builtin_unstable_features,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1361,21 +1393,25 @@ impl UnreachablePub {
|
|||||||
applicability = Applicability::MaybeIncorrect;
|
applicability = Applicability::MaybeIncorrect;
|
||||||
}
|
}
|
||||||
let def_span = cx.tcx.def_span(def_id);
|
let def_span = cx.tcx.def_span(def_id);
|
||||||
cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
|
UNREACHABLE_PUB,
|
||||||
err.set_arg("what", what);
|
def_span,
|
||||||
|
fluent::lint::builtin_unreachable_pub,
|
||||||
|
|lint| {
|
||||||
|
lint.set_arg("what", what);
|
||||||
|
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
vis_span,
|
vis_span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
"pub(crate)",
|
"pub(crate)",
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
if exportable {
|
if exportable {
|
||||||
err.help(fluent::lint::help);
|
lint.help(fluent::lint::help);
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1505,36 +1541,34 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
|||||||
|
|
||||||
let mut suggested_changing_assoc_types = false;
|
let mut suggested_changing_assoc_types = false;
|
||||||
if !where_spans.is_empty() {
|
if !where_spans.is_empty() {
|
||||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_where_clause, |lint| {
|
||||||
let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause);
|
lint.set_span(where_spans);
|
||||||
err.set_span(where_spans);
|
lint.span_suggestion(
|
||||||
err.span_suggestion(
|
|
||||||
type_alias_generics.where_clause_span,
|
type_alias_generics.where_clause_span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
"",
|
"",
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
if !suggested_changing_assoc_types {
|
if !suggested_changing_assoc_types {
|
||||||
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
|
TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
|
||||||
suggested_changing_assoc_types = true;
|
suggested_changing_assoc_types = true;
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inline_spans.is_empty() {
|
if !inline_spans.is_empty() {
|
||||||
cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
|
cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint::builtin_type_alias_generic_bounds, |lint| {
|
||||||
let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds);
|
lint.set_span(inline_spans);
|
||||||
err.set_span(inline_spans);
|
lint.multipart_suggestion(
|
||||||
err.multipart_suggestion(
|
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
inline_sugg,
|
inline_sugg,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
if !suggested_changing_assoc_types {
|
if !suggested_changing_assoc_types {
|
||||||
TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
|
TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1633,12 +1667,15 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
|||||||
TypeWellFormedFromEnv(..) => continue,
|
TypeWellFormedFromEnv(..) => continue,
|
||||||
};
|
};
|
||||||
if predicate.is_global() {
|
if predicate.is_global() {
|
||||||
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_trivial_bounds)
|
TRIVIAL_BOUNDS,
|
||||||
.set_arg("predicate_kind_name", predicate_kind_name)
|
span,
|
||||||
.set_arg("predicate", predicate)
|
fluent::lint::builtin_trivial_bounds,
|
||||||
.emit();
|
|lint| {
|
||||||
});
|
lint.set_arg("predicate_kind_name", predicate_kind_name)
|
||||||
|
.set_arg("predicate", predicate)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1754,15 +1791,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
|||||||
replace,
|
replace,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
|
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg, |lint| {
|
||||||
lint.build(msg)
|
lint.span_suggestion(
|
||||||
.span_suggestion(
|
pat.span,
|
||||||
pat.span,
|
suggestion,
|
||||||
suggestion,
|
replace,
|
||||||
replace,
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
)
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1774,15 +1809,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
|||||||
replace: replace.to_string(),
|
replace: replace.to_string(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
|
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg, |lint| {
|
||||||
lint.build(msg)
|
lint.span_suggestion_short(
|
||||||
.span_suggestion_short(
|
join,
|
||||||
join,
|
suggestion,
|
||||||
suggestion,
|
replace,
|
||||||
replace,
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
)
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1863,9 +1896,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
|
|||||||
|
|
||||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||||
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
|
||||||
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_unnameable_test_items).emit();
|
UNNAMEABLE_TEST_ITEMS,
|
||||||
});
|
attr.span,
|
||||||
|
fluent::lint::builtin_unnameable_test_items,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1981,18 +2017,19 @@ impl KeywordIdents {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_keyword_idents)
|
KEYWORD_IDENTS,
|
||||||
.set_arg("kw", ident.clone())
|
ident.span,
|
||||||
.set_arg("next", next_edition)
|
fluent::lint::builtin_keyword_idents,
|
||||||
.span_suggestion(
|
|lint| {
|
||||||
|
lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion(
|
||||||
ident.span,
|
ident.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
format!("r#{}", ident),
|
format!("r#{}", ident),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2243,10 +2280,12 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !lint_spans.is_empty() {
|
if !lint_spans.is_empty() {
|
||||||
cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::builtin_explicit_outlives)
|
EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||||
.set_arg("count", bound_count)
|
lint_spans.clone(),
|
||||||
.multipart_suggestion(
|
fluent::lint::builtin_explicit_outlives,
|
||||||
|
|lint| {
|
||||||
|
lint.set_arg("count", bound_count).multipart_suggestion(
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
lint_spans
|
lint_spans
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -2254,8 +2293,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2302,18 +2341,24 @@ impl EarlyLintPass for IncompleteFeatures {
|
|||||||
.chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
|
.chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
|
||||||
.filter(|(&name, _)| features.incomplete(name))
|
.filter(|(&name, _)| features.incomplete(name))
|
||||||
.for_each(|(&name, &span)| {
|
.for_each(|(&name, &span)| {
|
||||||
cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut builder = lint.build(fluent::lint::builtin_incomplete_features);
|
INCOMPLETE_FEATURES,
|
||||||
builder.set_arg("name", name);
|
span,
|
||||||
if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) {
|
fluent::lint::builtin_incomplete_features,
|
||||||
builder.set_arg("n", n);
|
|lint| {
|
||||||
builder.note(fluent::lint::note);
|
lint.set_arg("name", name);
|
||||||
}
|
if let Some(n) =
|
||||||
if HAS_MIN_FEATURES.contains(&name) {
|
rustc_feature::find_feature_issue(name, GateIssue::Language)
|
||||||
builder.help(fluent::lint::help);
|
{
|
||||||
}
|
lint.set_arg("n", n);
|
||||||
builder.emit();
|
lint.note(fluent::lint::note);
|
||||||
})
|
}
|
||||||
|
if HAS_MIN_FEATURES.contains(&name) {
|
||||||
|
lint.help(fluent::lint::help);
|
||||||
|
}
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2628,28 +2673,37 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||||||
with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
|
with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
|
||||||
{
|
{
|
||||||
// FIXME(davidtwco): make translatable
|
// FIXME(davidtwco): make translatable
|
||||||
cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(&format!(
|
INVALID_VALUE,
|
||||||
"the type `{}` does not permit {}",
|
expr.span,
|
||||||
conjured_ty,
|
DelayDm(|| {
|
||||||
match init {
|
format!(
|
||||||
InitKind::Zeroed => "zero-initialization",
|
"the type `{}` does not permit {}",
|
||||||
InitKind::Uninit => "being left uninitialized",
|
conjured_ty,
|
||||||
},
|
match init {
|
||||||
));
|
InitKind::Zeroed => "zero-initialization",
|
||||||
err.span_label(expr.span, "this code causes undefined behavior when executed");
|
InitKind::Uninit => "being left uninitialized",
|
||||||
err.span_label(
|
},
|
||||||
expr.span,
|
)
|
||||||
"help: use `MaybeUninit<T>` instead, \
|
}),
|
||||||
|
|lint| {
|
||||||
|
lint.span_label(
|
||||||
|
expr.span,
|
||||||
|
"this code causes undefined behavior when executed",
|
||||||
|
);
|
||||||
|
lint.span_label(
|
||||||
|
expr.span,
|
||||||
|
"help: use `MaybeUninit<T>` instead, \
|
||||||
and only call `assume_init` after initialization is done",
|
and only call `assume_init` after initialization is done",
|
||||||
);
|
);
|
||||||
if let Some(span) = span {
|
if let Some(span) = span {
|
||||||
err.span_note(span, &msg);
|
lint.span_note(span, &msg);
|
||||||
} else {
|
} else {
|
||||||
err.note(&msg);
|
lint.note(&msg);
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2995,31 +3049,35 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
|
|||||||
SymbolName::Link(_, annot_span) => fi.span.to(annot_span),
|
SymbolName::Link(_, annot_span) => fi.span.to(annot_span),
|
||||||
};
|
};
|
||||||
// Finally, emit the diagnostic.
|
// Finally, emit the diagnostic.
|
||||||
|
|
||||||
|
let msg = if orig.get_name() == this_fi.ident.name {
|
||||||
|
fluent::lint::builtin_clashing_extern_same_name
|
||||||
|
} else {
|
||||||
|
fluent::lint::builtin_clashing_extern_diff_name
|
||||||
|
};
|
||||||
tcx.struct_span_lint_hir(
|
tcx.struct_span_lint_hir(
|
||||||
CLASHING_EXTERN_DECLARATIONS,
|
CLASHING_EXTERN_DECLARATIONS,
|
||||||
this_fi.hir_id(),
|
this_fi.hir_id(),
|
||||||
get_relevant_span(this_fi),
|
get_relevant_span(this_fi),
|
||||||
|
msg,
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut expected_str = DiagnosticStyledString::new();
|
let mut expected_str = DiagnosticStyledString::new();
|
||||||
expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false);
|
expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false);
|
||||||
let mut found_str = DiagnosticStyledString::new();
|
let mut found_str = DiagnosticStyledString::new();
|
||||||
found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
|
found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
|
||||||
|
|
||||||
lint.build(if orig.get_name() == this_fi.ident.name {
|
lint.set_arg("this_fi", this_fi.ident.name)
|
||||||
fluent::lint::builtin_clashing_extern_same_name
|
.set_arg("orig", orig.get_name())
|
||||||
} else {
|
.span_label(
|
||||||
fluent::lint::builtin_clashing_extern_diff_name
|
get_relevant_span(orig_fi),
|
||||||
})
|
fluent::lint::previous_decl_label,
|
||||||
.set_arg("this_fi", this_fi.ident.name)
|
)
|
||||||
.set_arg("orig", orig.get_name())
|
.span_label(
|
||||||
.span_label(
|
get_relevant_span(this_fi),
|
||||||
get_relevant_span(orig_fi),
|
fluent::lint::mismatch_label,
|
||||||
fluent::lint::previous_decl_label,
|
)
|
||||||
)
|
// FIXME(davidtwco): translatable expected/found
|
||||||
.span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label)
|
.note_expected_found(&"", expected_str, &"", found_str)
|
||||||
// FIXME(davidtwco): translatable expected/found
|
|
||||||
.note_expected_found(&"", expected_str, &"", found_str)
|
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -3100,11 +3158,12 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
|
|||||||
|
|
||||||
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
|
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
|
||||||
if is_null_ptr(cx, expr_deref) {
|
if is_null_ptr(cx, expr_deref) {
|
||||||
cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::builtin_deref_nullptr);
|
DEREF_NULLPTR,
|
||||||
err.span_label(expr.span, fluent::lint::label);
|
expr.span,
|
||||||
err.emit();
|
fluent::lint::builtin_deref_nullptr,
|
||||||
});
|
|lint| lint.span_label(expr.span, fluent::lint::label),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3214,9 +3273,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
|
|||||||
cx.lookup_with_diagnostics(
|
cx.lookup_with_diagnostics(
|
||||||
NAMED_ASM_LABELS,
|
NAMED_ASM_LABELS,
|
||||||
Some(target_spans),
|
Some(target_spans),
|
||||||
|diag| {
|
fluent::lint::builtin_asm_labels,
|
||||||
diag.build(fluent::lint::builtin_asm_labels).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||||
"only local labels of the form `<number>:` should be used in inline asm"
|
"only local labels of the form `<number>:` should be used in inline asm"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
@ -3288,16 +3346,14 @@ impl EarlyLintPass for SpecialModuleName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match item.ident.name.as_str() {
|
match item.ident.name.as_str() {
|
||||||
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
|
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for lib.rs", |lint| {
|
||||||
lint.build("found module declaration for lib.rs")
|
lint
|
||||||
.note("lib.rs is the root of this crate's library target")
|
.note("lib.rs is the root of this crate's library target")
|
||||||
.help("to refer to it from other targets, use the library's name as the path")
|
.help("to refer to it from other targets, use the library's name as the path")
|
||||||
.emit()
|
|
||||||
}),
|
}),
|
||||||
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
|
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for main.rs", |lint| {
|
||||||
lint.build("found module declaration for main.rs")
|
lint
|
||||||
.note("a binary crate cannot be used as library")
|
.note("a binary crate cannot be used as library")
|
||||||
.emit()
|
|
||||||
}),
|
}),
|
||||||
_ => continue
|
_ => continue
|
||||||
}
|
}
|
||||||
@ -3317,24 +3373,27 @@ impl EarlyLintPass for UnexpectedCfgs {
|
|||||||
for &(name, value) in cfg {
|
for &(name, value) in cfg {
|
||||||
if let Some(names_valid) = &check_cfg.names_valid {
|
if let Some(names_valid) = &check_cfg.names_valid {
|
||||||
if !names_valid.contains(&name) {
|
if !names_valid.contains(&name) {
|
||||||
cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
|
cx.lookup(
|
||||||
diag.build(fluent::lint::builtin_unexpected_cli_config_name)
|
UNEXPECTED_CFGS,
|
||||||
.help(fluent::lint::help)
|
None::<MultiSpan>,
|
||||||
.set_arg("name", name)
|
fluent::lint::builtin_unexpected_cli_config_name,
|
||||||
.emit();
|
|diag| diag.help(fluent::lint::help).set_arg("name", name),
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
if let Some(values) = &check_cfg.values_valid.get(&name) {
|
if let Some(values) = &check_cfg.values_valid.get(&name) {
|
||||||
if !values.contains(&value) {
|
if !values.contains(&value) {
|
||||||
cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
|
cx.lookup(
|
||||||
diag.build(fluent::lint::builtin_unexpected_cli_config_value)
|
UNEXPECTED_CFGS,
|
||||||
.help(fluent::lint::help)
|
None::<MultiSpan>,
|
||||||
.set_arg("name", name)
|
fluent::lint::builtin_unexpected_cli_config_value,
|
||||||
.set_arg("value", value)
|
|diag| {
|
||||||
.emit();
|
diag.help(fluent::lint::help)
|
||||||
});
|
.set_arg("name", name)
|
||||||
|
.set_arg("value", value)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,8 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
|
|||||||
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync;
|
use rustc_data_structures::sync;
|
||||||
use rustc_errors::add_elided_lifetime_in_path_suggestion;
|
use rustc_errors::{add_elided_lifetime_in_path_suggestion, DiagnosticBuilder, DiagnosticMessage};
|
||||||
use rustc_errors::{
|
use rustc_errors::{Applicability, DecorateLint, MultiSpan, SuggestionStyle};
|
||||||
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
|
|
||||||
};
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
@ -580,13 +578,14 @@ pub trait LintContext: Sized {
|
|||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<impl Into<MultiSpan>>,
|
span: Option<impl Into<MultiSpan>>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
diagnostic: BuiltinLintDiagnostics,
|
diagnostic: BuiltinLintDiagnostics,
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, span, |lint| {
|
// We first generate a blank diagnostic.
|
||||||
// We first generate a blank diagnostic.
|
self.lookup(lint, span, msg,|db| {
|
||||||
let mut db = lint.build("");
|
|
||||||
|
|
||||||
// Now, set up surrounding context.
|
// Now, set up surrounding context.
|
||||||
let sess = self.sess();
|
let sess = self.sess();
|
||||||
match diagnostic {
|
match diagnostic {
|
||||||
@ -660,7 +659,7 @@ pub trait LintContext: Sized {
|
|||||||
) => {
|
) => {
|
||||||
add_elided_lifetime_in_path_suggestion(
|
add_elided_lifetime_in_path_suggestion(
|
||||||
sess.source_map(),
|
sess.source_map(),
|
||||||
&mut db,
|
db,
|
||||||
n,
|
n,
|
||||||
path_span,
|
path_span,
|
||||||
incl_angl_brckt,
|
incl_angl_brckt,
|
||||||
@ -696,7 +695,7 @@ pub trait LintContext: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
|
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
|
||||||
stability::deprecation_suggestion(&mut db, "macro", suggestion, span)
|
stability::deprecation_suggestion(db, "macro", suggestion, span)
|
||||||
}
|
}
|
||||||
BuiltinLintDiagnostics::UnusedDocComment(span) => {
|
BuiltinLintDiagnostics::UnusedDocComment(span) => {
|
||||||
db.span_label(span, "rustdoc does not generate documentation for macro invocations");
|
db.span_label(span, "rustdoc does not generate documentation for macro invocations");
|
||||||
@ -867,7 +866,7 @@ pub trait LintContext: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rewrap `db`, and pass control to the user.
|
// Rewrap `db`, and pass control to the user.
|
||||||
decorate(LintDiagnosticBuilder::new(db));
|
decorate(db)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,7 +876,10 @@ pub trait LintContext: Sized {
|
|||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
|
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
|
||||||
@ -888,31 +890,39 @@ pub trait LintContext: Sized {
|
|||||||
span: S,
|
span: S,
|
||||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag));
|
self.lookup(lint, Some(span), decorator.msg(), |diag| decorator.decorate_lint(diag));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_span_lint<S: Into<MultiSpan>>(
|
fn struct_span_lint<S: Into<MultiSpan>>(
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: S,
|
span: S,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, Some(span), decorate);
|
self.lookup(lint, Some(span), msg, decorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
||||||
/// generated by `#[derive(LintDiagnostic)]`).
|
/// generated by `#[derive(LintDiagnostic)]`).
|
||||||
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
|
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
|
||||||
self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag));
|
self.lookup(lint, None as Option<Span>, decorator.msg(), |diag| {
|
||||||
|
decorator.decorate_lint(diag)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a lint at the appropriate level, with no associated span.
|
/// Emit a lint at the appropriate level, with no associated span.
|
||||||
fn lint(
|
fn lint(
|
||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.lookup(lint, None as Option<Span>, decorate);
|
self.lookup(lint, None as Option<Span>, msg, decorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This returns the lint level for the given lint at the current location.
|
/// This returns the lint level for the given lint at the current location.
|
||||||
@ -975,13 +985,16 @@ impl<'tcx> LintContext for LateContext<'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
let hir_id = self.last_node_with_lint_attrs;
|
let hir_id = self.last_node_with_lint_attrs;
|
||||||
|
|
||||||
match span {
|
match span {
|
||||||
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, decorate),
|
Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg, decorate),
|
||||||
None => self.tcx.struct_lint_node(lint, hir_id, decorate),
|
None => self.tcx.struct_lint_node(lint, hir_id, msg, decorate),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,9 +1019,12 @@ impl LintContext for EarlyContext<'_> {
|
|||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<S>,
|
span: Option<S>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
|
self.builder.struct_lint(lint, span.map(|s| s.into()), msg, decorate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lint_level(&self, lint: &'static Lint) -> Level {
|
fn get_lint_level(&self, lint: &'static Lint) -> Level {
|
||||||
|
@ -43,9 +43,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||||||
self.context.lookup_with_diagnostics(
|
self.context.lookup_with_diagnostics(
|
||||||
lint_id.lint,
|
lint_id.lint,
|
||||||
Some(span),
|
Some(span),
|
||||||
|lint| {
|
msg,
|
||||||
lint.build(msg).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
diagnostic,
|
diagnostic,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -50,26 +50,24 @@ fn enforce_mem_discriminant(
|
|||||||
) {
|
) {
|
||||||
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
||||||
if is_non_enum(ty_param) {
|
if is_non_enum(ty_param) {
|
||||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| {
|
cx.struct_span_lint(
|
||||||
builder
|
ENUM_INTRINSICS_NON_ENUMS,
|
||||||
.build(fluent::lint::enum_intrinsics_mem_discriminant)
|
expr_span,
|
||||||
.set_arg("ty_param", ty_param)
|
fluent::lint::enum_intrinsics_mem_discriminant,
|
||||||
.span_note(args_span, fluent::lint::note)
|
|lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::lint::note),
|
||||||
.emit();
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
|
fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
|
||||||
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
|
||||||
if is_non_enum(ty_param) {
|
if is_non_enum(ty_param) {
|
||||||
cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| {
|
cx.struct_span_lint(
|
||||||
builder
|
ENUM_INTRINSICS_NON_ENUMS,
|
||||||
.build(fluent::lint::enum_intrinsics_mem_variant)
|
span,
|
||||||
.set_arg("ty_param", ty_param)
|
fluent::lint::enum_intrinsics_mem_variant,
|
||||||
.note(fluent::lint::note)
|
|lint| lint.set_arg("ty_param", ty_param).note(fluent::lint::note),
|
||||||
.emit();
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,17 +43,17 @@ fn emit_unfulfilled_expectation_lint(
|
|||||||
builtin::UNFULFILLED_LINT_EXPECTATIONS,
|
builtin::UNFULFILLED_LINT_EXPECTATIONS,
|
||||||
hir_id,
|
hir_id,
|
||||||
expectation.emission_span,
|
expectation.emission_span,
|
||||||
|diag| {
|
fluent::lint::expectation,
|
||||||
let mut diag = diag.build(fluent::lint::expectation);
|
|lint| {
|
||||||
if let Some(rationale) = expectation.reason {
|
if let Some(rationale) = expectation.reason {
|
||||||
diag.note(rationale.as_str());
|
lint.note(rationale.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if expectation.is_unfulfilled_lint_expectations {
|
if expectation.is_unfulfilled_lint_expectations {
|
||||||
diag.note(fluent::lint::note);
|
lint.note(fluent::lint::note);
|
||||||
}
|
}
|
||||||
|
|
||||||
diag.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -60,52 +60,56 @@ impl HiddenUnicodeCodepoints {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::hidden_unicode_codepoints);
|
TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
|
||||||
err.set_arg("label", label);
|
span,
|
||||||
err.set_arg("count", spans.len());
|
fluent::lint::hidden_unicode_codepoints,
|
||||||
err.span_label(span, fluent::lint::label);
|
|lint| {
|
||||||
err.note(fluent::lint::note);
|
lint.set_arg("label", label);
|
||||||
if point_at_inner_spans {
|
lint.set_arg("count", spans.len());
|
||||||
for (c, span) in &spans {
|
lint.span_label(span, fluent::lint::label);
|
||||||
err.span_label(*span, format!("{:?}", c));
|
lint.note(fluent::lint::note);
|
||||||
|
if point_at_inner_spans {
|
||||||
|
for (c, span) in &spans {
|
||||||
|
lint.span_label(*span, format!("{:?}", c));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if point_at_inner_spans && !spans.is_empty() {
|
||||||
if point_at_inner_spans && !spans.is_empty() {
|
lint.multipart_suggestion_with_style(
|
||||||
err.multipart_suggestion_with_style(
|
fluent::lint::suggestion_remove,
|
||||||
fluent::lint::suggestion_remove,
|
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
|
||||||
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
SuggestionStyle::HideCodeAlways,
|
||||||
SuggestionStyle::HideCodeAlways,
|
);
|
||||||
);
|
lint.multipart_suggestion(
|
||||||
err.multipart_suggestion(
|
fluent::lint::suggestion_escape,
|
||||||
fluent::lint::suggestion_escape,
|
spans
|
||||||
spans
|
.into_iter()
|
||||||
.into_iter()
|
.map(|(c, span)| {
|
||||||
.map(|(c, span)| {
|
let c = format!("{:?}", c);
|
||||||
let c = format!("{:?}", c);
|
(span, c[1..c.len() - 1].to_string())
|
||||||
(span, c[1..c.len() - 1].to_string())
|
})
|
||||||
})
|
.collect(),
|
||||||
.collect(),
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
||||||
// FIXME: in other suggestions we've reversed the inner spans of doc comments. We
|
// should do the same here to provide the same good suggestions as we do for
|
||||||
// should do the same here to provide the same good suggestions as we do for
|
// literals above.
|
||||||
// literals above.
|
lint.set_arg(
|
||||||
err.set_arg(
|
"escaped",
|
||||||
"escaped",
|
spans
|
||||||
spans
|
.into_iter()
|
||||||
.into_iter()
|
.map(|(c, _)| format!("{:?}", c))
|
||||||
.map(|(c, _)| format!("{:?}", c))
|
.collect::<Vec<String>>()
|
||||||
.collect::<Vec<String>>()
|
.join(", "),
|
||||||
.join(", "),
|
);
|
||||||
);
|
lint.note(fluent::lint::suggestion_remove);
|
||||||
err.note(fluent::lint::suggestion_remove);
|
lint.note(fluent::lint::no_suggestion_note_escape);
|
||||||
err.note(fluent::lint::no_suggestion_note_escape);
|
}
|
||||||
}
|
lint
|
||||||
err.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl EarlyLintPass for HiddenUnicodeCodepoints {
|
impl EarlyLintPass for HiddenUnicodeCodepoints {
|
||||||
|
@ -34,13 +34,16 @@ impl LateLintPass<'_> for DefaultHashTypes {
|
|||||||
Some(sym::HashSet) => "FxHashSet",
|
Some(sym::HashSet) => "FxHashSet",
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::default_hash_types)
|
DEFAULT_HASH_TYPES,
|
||||||
.set_arg("preferred", replace)
|
path.span,
|
||||||
.set_arg("used", cx.tcx.item_name(def_id))
|
fluent::lint::default_hash_types,
|
||||||
.note(fluent::lint::note)
|
|lint| {
|
||||||
.emit();
|
lint.set_arg("preferred", replace)
|
||||||
});
|
.set_arg("used", cx.tcx.item_name(def_id))
|
||||||
|
.note(fluent::lint::note)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +83,12 @@ impl LateLintPass<'_> for QueryStability {
|
|||||||
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
|
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
|
||||||
let def_id = instance.def_id();
|
let def_id = instance.def_id();
|
||||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
||||||
cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::query_instability)
|
POTENTIAL_QUERY_INSTABILITY,
|
||||||
.set_arg("query", cx.tcx.item_name(def_id))
|
span,
|
||||||
.note(fluent::lint::note)
|
fluent::lint::query_instability,
|
||||||
.emit();
|
|lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::lint::note),
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,15 +126,14 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||||||
let span = path.span.with_hi(
|
let span = path.span.with_hi(
|
||||||
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
|
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
|
||||||
);
|
);
|
||||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
|
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint::tykind_kind, |lint| {
|
||||||
lint.build(fluent::lint::tykind_kind)
|
lint
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
span,
|
span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
"ty",
|
"ty",
|
||||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,76 +142,77 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||||||
match &ty.kind {
|
match &ty.kind {
|
||||||
TyKind::Path(QPath::Resolved(_, path)) => {
|
TyKind::Path(QPath::Resolved(_, path)) => {
|
||||||
if lint_ty_kind_usage(cx, &path.res) {
|
if lint_ty_kind_usage(cx, &path.res) {
|
||||||
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
|
let hir = cx.tcx.hir();
|
||||||
let hir = cx.tcx.hir();
|
let span = match hir.find(hir.get_parent_node(ty.hir_id)) {
|
||||||
match hir.find(hir.get_parent_node(ty.hir_id)) {
|
Some(Node::Pat(Pat {
|
||||||
Some(Node::Pat(Pat {
|
kind:
|
||||||
kind:
|
PatKind::Path(qpath)
|
||||||
PatKind::Path(qpath)
|
| PatKind::TupleStruct(qpath, ..)
|
||||||
| PatKind::TupleStruct(qpath, ..)
|
| PatKind::Struct(qpath, ..),
|
||||||
| PatKind::Struct(qpath, ..),
|
..
|
||||||
..
|
})) => {
|
||||||
})) => {
|
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
&& qpath_ty.hir_id == ty.hir_id
|
||||||
&& qpath_ty.hir_id == ty.hir_id
|
{
|
||||||
{
|
Some(path.span)
|
||||||
lint.build(fluent::lint::tykind_kind)
|
} else {
|
||||||
.span_suggestion(
|
None
|
||||||
path.span,
|
|
||||||
fluent::lint::suggestion,
|
|
||||||
"ty",
|
|
||||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(Node::Expr(Expr {
|
|
||||||
kind: ExprKind::Path(qpath),
|
|
||||||
..
|
|
||||||
})) => {
|
|
||||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
|
||||||
&& qpath_ty.hir_id == ty.hir_id
|
|
||||||
{
|
|
||||||
lint.build(fluent::lint::tykind_kind)
|
|
||||||
.span_suggestion(
|
|
||||||
path.span,
|
|
||||||
fluent::lint::suggestion,
|
|
||||||
"ty",
|
|
||||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Can't unify these two branches because qpath below is `&&` and above is `&`
|
|
||||||
// and `A | B` paths don't play well together with adjustments, apparently.
|
|
||||||
Some(Node::Expr(Expr {
|
|
||||||
kind: ExprKind::Struct(qpath, ..),
|
|
||||||
..
|
|
||||||
})) => {
|
|
||||||
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
|
||||||
&& qpath_ty.hir_id == ty.hir_id
|
|
||||||
{
|
|
||||||
lint.build(fluent::lint::tykind_kind)
|
|
||||||
.span_suggestion(
|
|
||||||
path.span,
|
|
||||||
fluent::lint::suggestion,
|
|
||||||
"ty",
|
|
||||||
Applicability::MaybeIncorrect, // ty maybe needs an import
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
lint.build(fluent::lint::tykind).help(fluent::lint::help).emit();
|
Some(Node::Expr(Expr {
|
||||||
})
|
kind: ExprKind::Path(qpath),
|
||||||
|
..
|
||||||
|
})) => {
|
||||||
|
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||||
|
&& qpath_ty.hir_id == ty.hir_id
|
||||||
|
{
|
||||||
|
Some(path.span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Can't unify these two branches because qpath below is `&&` and above is `&`
|
||||||
|
// and `A | B` paths don't play well together with adjustments, apparently.
|
||||||
|
Some(Node::Expr(Expr {
|
||||||
|
kind: ExprKind::Struct(qpath, ..),
|
||||||
|
..
|
||||||
|
})) => {
|
||||||
|
if let QPath::TypeRelative(qpath_ty, ..) = qpath
|
||||||
|
&& qpath_ty.hir_id == ty.hir_id
|
||||||
|
{
|
||||||
|
Some(path.span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
match span {
|
||||||
|
Some(span) => {
|
||||||
|
cx.struct_span_lint(
|
||||||
|
USAGE_OF_TY_TYKIND,
|
||||||
|
path.span,
|
||||||
|
fluent::lint::tykind_kind,
|
||||||
|
|lint| lint.span_suggestion(
|
||||||
|
span,
|
||||||
|
fluent::lint::suggestion,
|
||||||
|
"ty",
|
||||||
|
Applicability::MaybeIncorrect, // ty maybe needs an import
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
None => cx.struct_span_lint(
|
||||||
|
USAGE_OF_TY_TYKIND,
|
||||||
|
path.span,
|
||||||
|
fluent::lint::tykind,
|
||||||
|
|lint| lint.help(fluent::lint::help)
|
||||||
|
)
|
||||||
|
}
|
||||||
} else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
|
} else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
|
||||||
if path.segments.len() > 1 {
|
if path.segments.len() > 1 {
|
||||||
cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
|
cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint::ty_qualified, |lint| {
|
||||||
lint.build(fluent::lint::ty_qualified)
|
lint
|
||||||
.set_arg("ty", t.clone())
|
.set_arg("ty", t.clone())
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
path.span,
|
path.span,
|
||||||
@ -218,7 +221,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
|||||||
// The import probably needs to be changed
|
// The import probably needs to be changed
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,11 +310,8 @@ impl EarlyLintPass for LintPassImpl {
|
|||||||
cx.struct_span_lint(
|
cx.struct_span_lint(
|
||||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||||
lint_pass.path.span,
|
lint_pass.path.span,
|
||||||
|lint| {
|
fluent::lint::lintpass_by_hand,
|
||||||
lint.build(fluent::lint::lintpass_by_hand)
|
|lint| lint.help(fluent::lint::help),
|
||||||
.help(fluent::lint::help)
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,12 +348,12 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
|
|||||||
if is_doc_keyword(v) {
|
if is_doc_keyword(v) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::non_existant_doc_keyword)
|
EXISTING_DOC_KEYWORD,
|
||||||
.set_arg("keyword", v)
|
attr.span,
|
||||||
.help(fluent::lint::help)
|
fluent::lint::non_existant_doc_keyword,
|
||||||
.emit();
|
|lint| lint.set_arg("keyword", v).help(fluent::lint::help),
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,9 +411,12 @@ impl LateLintPass<'_> for Diagnostics {
|
|||||||
}
|
}
|
||||||
debug!(?found_impl);
|
debug!(?found_impl);
|
||||||
if !found_parent_with_attr && !found_impl {
|
if !found_parent_with_attr && !found_impl {
|
||||||
cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::diag_out_of_impl).emit();
|
DIAGNOSTIC_OUTSIDE_OF_IMPL,
|
||||||
})
|
span,
|
||||||
|
fluent::lint::diag_out_of_impl,
|
||||||
|
|lint| lint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut found_diagnostic_message = false;
|
let mut found_diagnostic_message = false;
|
||||||
@ -430,9 +432,12 @@ impl LateLintPass<'_> for Diagnostics {
|
|||||||
}
|
}
|
||||||
debug!(?found_diagnostic_message);
|
debug!(?found_diagnostic_message);
|
||||||
if !found_parent_with_attr && !found_diagnostic_message {
|
if !found_parent_with_attr && !found_diagnostic_message {
|
||||||
cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::untranslatable_diag).emit();
|
UNTRANSLATABLE_DIAGNOSTIC,
|
||||||
})
|
span,
|
||||||
|
fluent::lint::untranslatable_diag,
|
||||||
|
|lint| lint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,8 +469,8 @@ impl LateLintPass<'_> for BadOptAccess {
|
|||||||
let Some(literal) = item.literal() &&
|
let Some(literal) = item.literal() &&
|
||||||
let ast::LitKind::Str(val, _) = literal.kind
|
let ast::LitKind::Str(val, _) = literal.kind
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, |lint| {
|
cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, val.as_str(), |lint|
|
||||||
lint.build(val.as_str()).emit(); }
|
lint
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{LateContext, LateLintPass, LintContext};
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan};
|
use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
@ -128,48 +128,41 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
|||||||
init.span,
|
init.span,
|
||||||
"this binding will immediately drop the value assigned to it".to_string(),
|
"this binding will immediately drop the value assigned to it".to_string(),
|
||||||
);
|
);
|
||||||
cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| {
|
cx.struct_span_lint(
|
||||||
build_and_emit_lint(
|
LET_UNDERSCORE_LOCK,
|
||||||
lint,
|
span,
|
||||||
local,
|
"non-binding let on a synchronization lock",
|
||||||
init.span,
|
|lint| build_lint(lint, local, init.span),
|
||||||
"non-binding let on a synchronization lock",
|
)
|
||||||
)
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
|
cx.struct_span_lint(
|
||||||
build_and_emit_lint(
|
LET_UNDERSCORE_DROP,
|
||||||
lint,
|
local.span,
|
||||||
local,
|
"non-binding let on a type that implements `Drop`",
|
||||||
init.span,
|
|lint| build_lint(lint, local, init.span),
|
||||||
"non-binding let on a type that implements `Drop`",
|
)
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_and_emit_lint(
|
fn build_lint<'a, 'b>(
|
||||||
lint: LintDiagnosticBuilder<'_, ()>,
|
lint: &'a mut DiagnosticBuilder<'b, ()>,
|
||||||
local: &hir::Local<'_>,
|
local: &hir::Local<'_>,
|
||||||
init_span: rustc_span::Span,
|
init_span: rustc_span::Span,
|
||||||
msg: &str,
|
) -> &'a mut DiagnosticBuilder<'b, ()> {
|
||||||
) {
|
lint.span_suggestion_verbose(
|
||||||
lint.build(msg)
|
local.pat.span,
|
||||||
.span_suggestion_verbose(
|
"consider binding to an unused variable to avoid immediately dropping the value",
|
||||||
local.pat.span,
|
"_unused",
|
||||||
"consider binding to an unused variable to avoid immediately dropping the value",
|
Applicability::MachineApplicable,
|
||||||
"_unused",
|
)
|
||||||
Applicability::MachineApplicable,
|
.multipart_suggestion(
|
||||||
)
|
"consider immediately dropping the value",
|
||||||
.multipart_suggestion(
|
vec![
|
||||||
"consider immediately dropping the value",
|
(local.span.until(init_span), "drop(".to_string()),
|
||||||
vec![
|
(init_span.shrink_to_hi(), ")".to_string()),
|
||||||
(local.span.until(init_span), "drop(".to_string()),
|
],
|
||||||
(init_span.shrink_to_hi(), ")".to_string()),
|
Applicability::MachineApplicable,
|
||||||
],
|
)
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::late::unerased_lint_store;
|
|||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{intravisit, HirId};
|
use rustc_hir::{intravisit, HirId};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
@ -214,14 +214,14 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
self.struct_lint(
|
self.struct_lint(
|
||||||
FORBIDDEN_LINT_GROUPS,
|
FORBIDDEN_LINT_GROUPS,
|
||||||
Some(src.span().into()),
|
Some(src.span().into()),
|
||||||
|diag_builder| {
|
format!(
|
||||||
let mut diag_builder = diag_builder.build(&format!(
|
"{}({}) incompatible with previous forbid",
|
||||||
"{}({}) incompatible with previous forbid",
|
level.as_str(),
|
||||||
level.as_str(),
|
src.name(),
|
||||||
src.name(),
|
),
|
||||||
));
|
|lint| {
|
||||||
decorate_diag(&mut diag_builder);
|
decorate_diag(lint);
|
||||||
diag_builder.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -466,20 +466,18 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
lvl,
|
lvl,
|
||||||
src,
|
src,
|
||||||
Some(sp.into()),
|
Some(sp.into()),
|
||||||
|
format!(
|
||||||
|
"lint name `{}` is deprecated \
|
||||||
|
and may not have an effect in the future.",
|
||||||
|
name
|
||||||
|
),
|
||||||
|lint| {
|
|lint| {
|
||||||
let msg = format!(
|
lint.span_suggestion(
|
||||||
"lint name `{}` is deprecated \
|
sp,
|
||||||
and may not have an effect in the future.",
|
"change it to",
|
||||||
name
|
new_lint_name,
|
||||||
);
|
Applicability::MachineApplicable,
|
||||||
lint.build(&msg)
|
)
|
||||||
.span_suggestion(
|
|
||||||
sp,
|
|
||||||
"change it to",
|
|
||||||
new_lint_name,
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -533,17 +531,17 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
renamed_lint_level,
|
renamed_lint_level,
|
||||||
src,
|
src,
|
||||||
Some(sp.into()),
|
Some(sp.into()),
|
||||||
|
msg,
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build(msg);
|
|
||||||
if let Some(new_name) = &renamed {
|
if let Some(new_name) = &renamed {
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
sp,
|
sp,
|
||||||
"use the new name",
|
"use the new name",
|
||||||
new_name,
|
new_name,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -555,23 +553,30 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
Some(self.current_specs()),
|
Some(self.current_specs()),
|
||||||
self.sess,
|
self.sess,
|
||||||
);
|
);
|
||||||
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
|
let name = if let Some(tool_ident) = tool_ident {
|
||||||
let name = if let Some(tool_ident) = tool_ident {
|
format!("{}::{}", tool_ident.name, name)
|
||||||
format!("{}::{}", tool_ident.name, name)
|
} else {
|
||||||
} else {
|
name.to_string()
|
||||||
name.to_string()
|
};
|
||||||
};
|
struct_lint_level(
|
||||||
let mut db = lint.build(format!("unknown lint: `{}`", name));
|
self.sess,
|
||||||
if let Some(suggestion) = suggestion {
|
lint,
|
||||||
db.span_suggestion(
|
level,
|
||||||
sp,
|
src,
|
||||||
"did you mean",
|
Some(sp.into()),
|
||||||
suggestion,
|
format!("unknown lint: `{}`", name),
|
||||||
Applicability::MachineApplicable,
|
|lint| {
|
||||||
);
|
if let Some(suggestion) = suggestion {
|
||||||
}
|
lint.span_suggestion(
|
||||||
db.emit();
|
sp,
|
||||||
});
|
"did you mean",
|
||||||
|
suggestion,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
|
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
|
||||||
@ -621,14 +626,12 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
lint_level,
|
lint_level,
|
||||||
lint_src,
|
lint_src,
|
||||||
Some(lint_attr_span.into()),
|
Some(lint_attr_span.into()),
|
||||||
|lint| {
|
format!(
|
||||||
let mut db = lint.build(&format!(
|
"{}({}) is ignored unless specified at crate level",
|
||||||
"{}({}) is ignored unless specified at crate level",
|
level.as_str(),
|
||||||
level.as_str(),
|
lint_attr_name
|
||||||
lint_attr_name
|
),
|
||||||
));
|
|lint| lint,
|
||||||
db.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
// don't set a separate error for every lint in the group
|
// don't set a separate error for every lint in the group
|
||||||
break;
|
break;
|
||||||
@ -665,13 +668,21 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
if !self.sess.features_untracked().enabled(feature) {
|
if !self.sess.features_untracked().enabled(feature) {
|
||||||
let lint = builtin::UNKNOWN_LINTS;
|
let lint = builtin::UNKNOWN_LINTS;
|
||||||
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
|
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
|
||||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), |lint_db| {
|
struct_lint_level(
|
||||||
let mut db =
|
self.sess,
|
||||||
lint_db.build(&format!("unknown lint: `{}`", lint_id.lint.name_lower()));
|
lint,
|
||||||
db.note(&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),));
|
level,
|
||||||
add_feature_diagnostics(&mut db, &self.sess.parse_sess, feature);
|
src,
|
||||||
db.emit();
|
Some(span.into()),
|
||||||
});
|
format!("unknown lint: `{}`", lint_id.lint.name_lower()),
|
||||||
|
|lint| {
|
||||||
|
lint.note(
|
||||||
|
&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),),
|
||||||
|
);
|
||||||
|
add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -694,10 +705,13 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||||||
&self,
|
&self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level(lint);
|
let (level, src) = self.lint_level(lint);
|
||||||
struct_lint_level(self.sess, lint, level, src, span, decorate)
|
struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers the ID provided with the current set of lints stored in
|
/// Registers the ID provided with the current set of lints stored in
|
||||||
|
@ -90,14 +90,17 @@ fn lint_cstring_as_ptr(
|
|||||||
if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
|
if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
|
||||||
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
|
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
|
||||||
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
|
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
|
||||||
cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| {
|
cx.struct_span_lint(
|
||||||
diag.build(fluent::lint::cstring_ptr)
|
TEMPORARY_CSTRING_AS_PTR,
|
||||||
.span_label(as_ptr_span, fluent::lint::as_ptr_label)
|
as_ptr_span,
|
||||||
.span_label(unwrap.span, fluent::lint::unwrap_label)
|
fluent::lint::cstring_ptr,
|
||||||
.note(fluent::lint::note)
|
|diag| {
|
||||||
.help(fluent::lint::help)
|
diag.span_label(as_ptr_span, fluent::lint::as_ptr_label)
|
||||||
.emit();
|
.span_label(unwrap.span, fluent::lint::unwrap_label)
|
||||||
});
|
.note(fluent::lint::note)
|
||||||
|
.help(fluent::lint::help)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,15 +180,21 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
has_non_ascii_idents = true;
|
has_non_ascii_idents = true;
|
||||||
cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::identifier_non_ascii_char).emit();
|
NON_ASCII_IDENTS,
|
||||||
});
|
sp,
|
||||||
|
fluent::lint::identifier_non_ascii_char,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
if check_uncommon_codepoints
|
if check_uncommon_codepoints
|
||||||
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::identifier_uncommon_codepoints).emit();
|
UNCOMMON_CODEPOINTS,
|
||||||
})
|
sp,
|
||||||
|
fluent::lint::identifier_uncommon_codepoints,
|
||||||
|
|lint| lint,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,13 +222,16 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||||||
.entry(skeleton_sym)
|
.entry(skeleton_sym)
|
||||||
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
|
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
|
||||||
if !*existing_is_ascii || !is_ascii {
|
if !*existing_is_ascii || !is_ascii {
|
||||||
cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::confusable_identifier_pair)
|
CONFUSABLE_IDENTS,
|
||||||
.set_arg("existing_sym", *existing_symbol)
|
sp,
|
||||||
.set_arg("sym", symbol)
|
fluent::lint::confusable_identifier_pair,
|
||||||
.span_label(*existing_span, fluent::lint::label)
|
|lint| {
|
||||||
.emit();
|
lint.set_arg("existing_sym", *existing_symbol)
|
||||||
});
|
.set_arg("sym", symbol)
|
||||||
|
.span_label(*existing_span, fluent::lint::label)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if *existing_is_ascii && !is_ascii {
|
if *existing_is_ascii && !is_ascii {
|
||||||
*existing_symbol = symbol;
|
*existing_symbol = symbol;
|
||||||
@ -322,22 +331,25 @@ impl EarlyLintPass for NonAsciiIdents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ((sp, ch_list), script_set) in lint_reports {
|
for ((sp, ch_list), script_set) in lint_reports {
|
||||||
cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut includes = String::new();
|
MIXED_SCRIPT_CONFUSABLES,
|
||||||
for (idx, ch) in ch_list.into_iter().enumerate() {
|
sp,
|
||||||
if idx != 0 {
|
fluent::lint::mixed_script_confusables,
|
||||||
includes += ", ";
|
|lint| {
|
||||||
|
let mut includes = String::new();
|
||||||
|
for (idx, ch) in ch_list.into_iter().enumerate() {
|
||||||
|
if idx != 0 {
|
||||||
|
includes += ", ";
|
||||||
|
}
|
||||||
|
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
||||||
|
includes += &char_info;
|
||||||
}
|
}
|
||||||
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
|
lint.set_arg("set", script_set.to_string())
|
||||||
includes += &char_info;
|
.set_arg("includes", includes)
|
||||||
}
|
.note(fluent::lint::includes_note)
|
||||||
lint.build(fluent::lint::mixed_script_confusables)
|
.note(fluent::lint::note)
|
||||||
.set_arg("set", script_set.to_string())
|
},
|
||||||
.set_arg("includes", includes)
|
);
|
||||||
.note(fluent::lint::includes_note)
|
|
||||||
.note(fluent::lint::note)
|
|
||||||
.emit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,21 +119,19 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
arg_span = expn.call_site;
|
arg_span = expn.call_site;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
|
cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint::non_fmt_panic, |lint| {
|
||||||
let mut l = lint.build(fluent::lint::non_fmt_panic);
|
lint.set_arg("name", symbol);
|
||||||
l.set_arg("name", symbol);
|
lint.note(fluent::lint::note);
|
||||||
l.note(fluent::lint::note);
|
lint.note(fluent::lint::more_info_note);
|
||||||
l.note(fluent::lint::more_info_note);
|
|
||||||
if !is_arg_inside_call(arg_span, span) {
|
if !is_arg_inside_call(arg_span, span) {
|
||||||
// No clue where this argument is coming from.
|
// No clue where this argument is coming from.
|
||||||
l.emit();
|
return lint;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
|
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
|
||||||
// A case of `panic!(format!(..))`.
|
// A case of `panic!(format!(..))`.
|
||||||
l.note(fluent::lint::supports_fmt_note);
|
lint.note(fluent::lint::supports_fmt_note);
|
||||||
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
|
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
|
||||||
l.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
fluent::lint::supports_fmt_suggestion,
|
fluent::lint::supports_fmt_suggestion,
|
||||||
vec![
|
vec![
|
||||||
(arg_span.until(open.shrink_to_hi()), "".into()),
|
(arg_span.until(open.shrink_to_hi()), "".into()),
|
||||||
@ -180,15 +178,15 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
};
|
};
|
||||||
|
|
||||||
if suggest_display {
|
if suggest_display {
|
||||||
l.span_suggestion_verbose(
|
lint.span_suggestion_verbose(
|
||||||
arg_span.shrink_to_lo(),
|
arg_span.shrink_to_lo(),
|
||||||
fluent::lint::display_suggestion,
|
fluent::lint::display_suggestion,
|
||||||
"\"{}\", ",
|
"\"{}\", ",
|
||||||
fmt_applicability,
|
fmt_applicability,
|
||||||
);
|
);
|
||||||
} else if suggest_debug {
|
} else if suggest_debug {
|
||||||
l.set_arg("ty", ty);
|
lint.set_arg("ty", ty);
|
||||||
l.span_suggestion_verbose(
|
lint.span_suggestion_verbose(
|
||||||
arg_span.shrink_to_lo(),
|
arg_span.shrink_to_lo(),
|
||||||
fluent::lint::debug_suggestion,
|
fluent::lint::debug_suggestion,
|
||||||
"\"{:?}\", ",
|
"\"{:?}\", ",
|
||||||
@ -198,8 +196,8 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
|
|
||||||
if suggest_panic_any {
|
if suggest_panic_any {
|
||||||
if let Some((open, close, del)) = find_delimiters(cx, span) {
|
if let Some((open, close, del)) = find_delimiters(cx, span) {
|
||||||
l.set_arg("already_suggested", suggest_display || suggest_debug);
|
lint.set_arg("already_suggested", suggest_display || suggest_debug);
|
||||||
l.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
fluent::lint::panic_suggestion,
|
fluent::lint::panic_suggestion,
|
||||||
if del == '(' {
|
if del == '(' {
|
||||||
vec![(span.until(open), "std::panic::panic_any".into())]
|
vec![(span.until(open), "std::panic::panic_any".into())]
|
||||||
@ -214,7 +212,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,26 +256,30 @@ fn check_panic_str<'tcx>(
|
|||||||
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
|
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut l = lint.build(fluent::lint::non_fmt_panic_unused);
|
NON_FMT_PANICS,
|
||||||
l.set_arg("count", n_arguments);
|
arg_spans,
|
||||||
l.note(fluent::lint::note);
|
fluent::lint::non_fmt_panic_unused,
|
||||||
if is_arg_inside_call(arg.span, span) {
|
|lint| {
|
||||||
l.span_suggestion(
|
lint.set_arg("count", n_arguments);
|
||||||
arg.span.shrink_to_hi(),
|
lint.note(fluent::lint::note);
|
||||||
fluent::lint::add_args_suggestion,
|
if is_arg_inside_call(arg.span, span) {
|
||||||
", ...",
|
lint.span_suggestion(
|
||||||
Applicability::HasPlaceholders,
|
arg.span.shrink_to_hi(),
|
||||||
);
|
fluent::lint::add_args_suggestion,
|
||||||
l.span_suggestion(
|
", ...",
|
||||||
arg.span.shrink_to_lo(),
|
Applicability::HasPlaceholders,
|
||||||
fluent::lint::add_fmt_suggestion,
|
);
|
||||||
"\"{}\", ",
|
lint.span_suggestion(
|
||||||
Applicability::MachineApplicable,
|
arg.span.shrink_to_lo(),
|
||||||
);
|
fluent::lint::add_fmt_suggestion,
|
||||||
}
|
"\"{}\", ",
|
||||||
l.emit();
|
Applicability::MachineApplicable,
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let brace_spans: Option<Vec<_>> =
|
let brace_spans: Option<Vec<_>> =
|
||||||
snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| {
|
snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| {
|
||||||
@ -287,20 +289,24 @@ fn check_panic_str<'tcx>(
|
|||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
|
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
|
||||||
cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
|
cx.struct_span_lint(
|
||||||
let mut l = lint.build(fluent::lint::non_fmt_panic_braces);
|
NON_FMT_PANICS,
|
||||||
l.set_arg("count", count);
|
brace_spans.unwrap_or_else(|| vec![span]),
|
||||||
l.note(fluent::lint::note);
|
fluent::lint::non_fmt_panic_braces,
|
||||||
if is_arg_inside_call(arg.span, span) {
|
|lint| {
|
||||||
l.span_suggestion(
|
lint.set_arg("count", count);
|
||||||
arg.span.shrink_to_lo(),
|
lint.note(fluent::lint::note);
|
||||||
fluent::lint::suggestion,
|
if is_arg_inside_call(arg.span, span) {
|
||||||
"\"{}\", ",
|
lint.span_suggestion(
|
||||||
Applicability::MachineApplicable,
|
arg.span.shrink_to_lo(),
|
||||||
);
|
fluent::lint::suggestion,
|
||||||
}
|
"\"{}\", ",
|
||||||
l.emit();
|
Applicability::MachineApplicable,
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,26 +136,30 @@ impl NonCamelCaseTypes {
|
|||||||
let name = ident.name.as_str();
|
let name = ident.name.as_str();
|
||||||
|
|
||||||
if !is_camel_case(name) {
|
if !is_camel_case(name) {
|
||||||
cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let mut err = lint.build(fluent::lint::non_camel_case_type);
|
NON_CAMEL_CASE_TYPES,
|
||||||
let cc = to_camel_case(name);
|
ident.span,
|
||||||
// We cannot provide meaningful suggestions
|
fluent::lint::non_camel_case_type,
|
||||||
// if the characters are in the category of "Lowercase Letter".
|
|lint| {
|
||||||
if *name != cc {
|
let cc = to_camel_case(name);
|
||||||
err.span_suggestion(
|
// We cannot provide meaningful suggestions
|
||||||
ident.span,
|
// if the characters are in the category of "Lowercase Letter".
|
||||||
fluent::lint::suggestion,
|
if *name != cc {
|
||||||
to_camel_case(name),
|
lint.span_suggestion(
|
||||||
Applicability::MaybeIncorrect,
|
ident.span,
|
||||||
);
|
fluent::lint::suggestion,
|
||||||
} else {
|
to_camel_case(name),
|
||||||
err.span_label(ident.span, fluent::lint::label);
|
Applicability::MaybeIncorrect,
|
||||||
}
|
);
|
||||||
|
} else {
|
||||||
|
lint.span_label(ident.span, fluent::lint::label);
|
||||||
|
}
|
||||||
|
|
||||||
err.set_arg("sort", sort);
|
lint.set_arg("sort", sort);
|
||||||
err.set_arg("name", name);
|
lint.set_arg("name", name);
|
||||||
err.emit();
|
lint
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,9 +284,8 @@ impl NonSnakeCase {
|
|||||||
let name = ident.name.as_str();
|
let name = ident.name.as_str();
|
||||||
|
|
||||||
if !is_snake_case(name) {
|
if !is_snake_case(name) {
|
||||||
cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| {
|
cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint::non_snake_case, |lint| {
|
||||||
let sc = NonSnakeCase::to_snake_case(name);
|
let sc = NonSnakeCase::to_snake_case(name);
|
||||||
let mut err = lint.build(fluent::lint::non_snake_case);
|
|
||||||
// We cannot provide meaningful suggestions
|
// We cannot provide meaningful suggestions
|
||||||
// if the characters are in the category of "Uppercase Letter".
|
// if the characters are in the category of "Uppercase Letter".
|
||||||
if name != sc {
|
if name != sc {
|
||||||
@ -297,30 +300,30 @@ impl NonSnakeCase {
|
|||||||
if sc_ident.name.can_be_raw() {
|
if sc_ident.name.can_be_raw() {
|
||||||
(fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
|
(fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
|
||||||
} else {
|
} else {
|
||||||
err.note(fluent::lint::cannot_convert_note);
|
lint.note(fluent::lint::cannot_convert_note);
|
||||||
(fluent::lint::rename_suggestion, String::new())
|
(fluent::lint::rename_suggestion, String::new())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(fluent::lint::convert_suggestion, sc.clone())
|
(fluent::lint::convert_suggestion, sc.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
ident.span,
|
ident.span,
|
||||||
message,
|
message,
|
||||||
suggestion,
|
suggestion,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
err.help(fluent::lint::help);
|
lint.help(fluent::lint::help);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err.span_label(ident.span, fluent::lint::label);
|
lint.span_label(ident.span, fluent::lint::label);
|
||||||
}
|
}
|
||||||
|
|
||||||
err.set_arg("sort", sort);
|
lint.set_arg("sort", sort);
|
||||||
err.set_arg("name", name);
|
lint.set_arg("name", name);
|
||||||
err.set_arg("sc", sc);
|
lint.set_arg("sc", sc);
|
||||||
err.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,26 +481,30 @@ impl NonUpperCaseGlobals {
|
|||||||
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
|
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
|
||||||
let name = ident.name.as_str();
|
let name = ident.name.as_str();
|
||||||
if name.chars().any(|c| c.is_lowercase()) {
|
if name.chars().any(|c| c.is_lowercase()) {
|
||||||
cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
|
NON_UPPER_CASE_GLOBALS,
|
||||||
let mut err = lint.build(fluent::lint::non_upper_case_global);
|
ident.span,
|
||||||
// We cannot provide meaningful suggestions
|
fluent::lint::non_upper_case_global,
|
||||||
// if the characters are in the category of "Lowercase Letter".
|
|lint| {
|
||||||
if *name != uc {
|
let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
|
||||||
err.span_suggestion(
|
// We cannot provide meaningful suggestions
|
||||||
ident.span,
|
// if the characters are in the category of "Lowercase Letter".
|
||||||
fluent::lint::suggestion,
|
if *name != uc {
|
||||||
uc,
|
lint.span_suggestion(
|
||||||
Applicability::MaybeIncorrect,
|
ident.span,
|
||||||
);
|
fluent::lint::suggestion,
|
||||||
} else {
|
uc,
|
||||||
err.span_label(ident.span, fluent::lint::label);
|
Applicability::MaybeIncorrect,
|
||||||
}
|
);
|
||||||
|
} else {
|
||||||
|
lint.span_label(ident.span, fluent::lint::label);
|
||||||
|
}
|
||||||
|
|
||||||
err.set_arg("sort", sort);
|
lint.set_arg("sort", sort);
|
||||||
err.set_arg("name", name);
|
lint.set_arg("name", name);
|
||||||
err.emit();
|
lint
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,13 +90,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
|||||||
}
|
}
|
||||||
let expr_span = expr.span;
|
let expr_span = expr.span;
|
||||||
let span = expr_span.with_lo(receiver.span.hi());
|
let span = expr_span.with_lo(receiver.span.hi());
|
||||||
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
|
cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint::noop_method_call, |lint| {
|
||||||
lint.build(fluent::lint::noop_method_call)
|
lint.set_arg("method", call.ident.name)
|
||||||
.set_arg("method", call.ident.name)
|
|
||||||
.set_arg("receiver_ty", receiver_ty)
|
.set_arg("receiver_ty", receiver_ty)
|
||||||
.span_label(span, fluent::lint::label)
|
.span_label(span, fluent::lint::label)
|
||||||
.note(fluent::lint::note)
|
.note(fluent::lint::note)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,18 +29,20 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
||||||
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::pass_by_value)
|
PASS_BY_VALUE,
|
||||||
.set_arg("ty", t.clone())
|
ty.span,
|
||||||
.span_suggestion(
|
fluent::lint::pass_by_value,
|
||||||
|
|lint| {
|
||||||
|
lint.set_arg("ty", t.clone()).span_suggestion(
|
||||||
ty.span,
|
ty.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
t,
|
t,
|
||||||
// Changing type of function argument
|
// Changing type of function argument
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -48,11 +48,18 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::redundant_semicolons)
|
REDUNDANT_SEMICOLONS,
|
||||||
.set_arg("multiple", multiple)
|
span,
|
||||||
.span_suggestion(span, fluent::lint::suggestion, "", Applicability::MaybeIncorrect)
|
fluent::lint::redundant_semicolons,
|
||||||
.emit();
|
|lint| {
|
||||||
});
|
lint.set_arg("multiple", multiple).span_suggestion(
|
||||||
|
span,
|
||||||
|
fluent::lint::suggestion,
|
||||||
|
"",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,15 +100,18 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||||||
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
|
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
|
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
||||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
continue;
|
||||||
return
|
};
|
||||||
};
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::drop_trait_constraints)
|
DROP_BOUNDS,
|
||||||
.set_arg("predicate", predicate)
|
span,
|
||||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
fluent::lint::drop_trait_constraints,
|
||||||
.emit();
|
|lint| {
|
||||||
});
|
lint.set_arg("predicate", predicate)
|
||||||
|
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,14 +122,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
|
|||||||
};
|
};
|
||||||
for bound in &bounds[..] {
|
for bound in &bounds[..] {
|
||||||
let def_id = bound.trait_ref.trait_def_id();
|
let def_id = bound.trait_ref.trait_def_id();
|
||||||
if cx.tcx.lang_items().drop_trait() == def_id {
|
if cx.tcx.lang_items().drop_trait() == def_id
|
||||||
cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
|
&& let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop)
|
||||||
let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
|
{
|
||||||
return
|
cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint::drop_glue, |lint| {
|
||||||
};
|
lint.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
||||||
lint.build(fluent::lint::drop_glue)
|
|
||||||
.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
|
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,12 +144,18 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||||||
// We can suggest using an inclusive range
|
// We can suggest using an inclusive range
|
||||||
// (`..=`) instead only if it is the `end` that is
|
// (`..=`) instead only if it is the `end` that is
|
||||||
// overflowing and only by 1.
|
// overflowing and only by 1.
|
||||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
|
&& let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span)
|
||||||
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
|
{
|
||||||
err.set_arg("ty", ty);
|
cx.struct_span_lint(
|
||||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
OVERFLOWING_LITERALS,
|
||||||
|
struct_expr.span,
|
||||||
|
fluent::lint::range_endpoint_out_of_range,
|
||||||
|
|lint| {
|
||||||
use ast::{LitIntType, LitKind};
|
use ast::{LitIntType, LitKind};
|
||||||
|
|
||||||
|
lint.set_arg("ty", ty);
|
||||||
|
|
||||||
// We need to preserve the literal's suffix,
|
// We need to preserve the literal's suffix,
|
||||||
// as it may determine typing information.
|
// as it may determine typing information.
|
||||||
let suffix = match lit.node {
|
let suffix = match lit.node {
|
||||||
@ -159,16 +165,17 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
struct_expr.span,
|
struct_expr.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
suggestion,
|
suggestion,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.emit();
|
|
||||||
overwritten = true;
|
overwritten = true;
|
||||||
}
|
|
||||||
});
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
overwritten
|
overwritten
|
||||||
}
|
}
|
||||||
@ -221,52 +228,58 @@ fn report_bin_hex_error(
|
|||||||
negative: bool,
|
negative: bool,
|
||||||
) {
|
) {
|
||||||
let size = Integer::from_attr(&cx.tcx, ty).size();
|
let size = Integer::from_attr(&cx.tcx, ty).size();
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
|
cx.struct_span_lint(
|
||||||
let (t, actually) = match ty {
|
OVERFLOWING_LITERALS,
|
||||||
attr::IntType::SignedInt(t) => {
|
expr.span,
|
||||||
let actually = if negative {
|
fluent::lint::overflowing_bin_hex,
|
||||||
-(size.sign_extend(val) as i128)
|
|lint| {
|
||||||
} else {
|
let (t, actually) = match ty {
|
||||||
size.sign_extend(val) as i128
|
attr::IntType::SignedInt(t) => {
|
||||||
};
|
let actually = if negative {
|
||||||
(t.name_str(), actually.to_string())
|
-(size.sign_extend(val) as i128)
|
||||||
}
|
} else {
|
||||||
attr::IntType::UnsignedInt(t) => {
|
size.sign_extend(val) as i128
|
||||||
let actually = size.truncate(val);
|
};
|
||||||
(t.name_str(), actually.to_string())
|
(t.name_str(), actually.to_string())
|
||||||
}
|
}
|
||||||
};
|
attr::IntType::UnsignedInt(t) => {
|
||||||
let mut err = lint.build(fluent::lint::overflowing_bin_hex);
|
let actually = size.truncate(val);
|
||||||
if negative {
|
(t.name_str(), actually.to_string())
|
||||||
// If the value is negative,
|
}
|
||||||
// emits a note about the value itself, apart from the literal.
|
};
|
||||||
err.note(fluent::lint::negative_note);
|
|
||||||
err.note(fluent::lint::negative_becomes_note);
|
if negative {
|
||||||
} else {
|
// If the value is negative,
|
||||||
err.note(fluent::lint::positive_note);
|
// emits a note about the value itself, apart from the literal.
|
||||||
}
|
lint.note(fluent::lint::negative_note);
|
||||||
if let Some(sugg_ty) =
|
lint.note(fluent::lint::negative_becomes_note);
|
||||||
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
|
|
||||||
{
|
|
||||||
err.set_arg("suggestion_ty", sugg_ty);
|
|
||||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
|
||||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
|
||||||
err.span_suggestion(
|
|
||||||
expr.span,
|
|
||||||
fluent::lint::suggestion,
|
|
||||||
format!("{}{}", sans_suffix, sugg_ty),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
err.help(fluent::lint::help);
|
lint.note(fluent::lint::positive_note);
|
||||||
}
|
}
|
||||||
}
|
if let Some(sugg_ty) =
|
||||||
err.set_arg("ty", t);
|
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
|
||||||
err.set_arg("lit", repr_str);
|
{
|
||||||
err.set_arg("dec", val);
|
lint.set_arg("suggestion_ty", sugg_ty);
|
||||||
err.set_arg("actually", actually);
|
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||||
err.emit();
|
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||||
});
|
lint.span_suggestion(
|
||||||
|
expr.span,
|
||||||
|
fluent::lint::suggestion,
|
||||||
|
format!("{}{}", sans_suffix, sugg_ty),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
lint.help(fluent::lint::help);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lint.set_arg("ty", t)
|
||||||
|
.set_arg("lit", repr_str)
|
||||||
|
.set_arg("dec", val)
|
||||||
|
.set_arg("actually", actually);
|
||||||
|
|
||||||
|
lint
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function finds the next fitting type and generates a suggestion string.
|
// This function finds the next fitting type and generates a suggestion string.
|
||||||
@ -349,26 +362,27 @@ fn lint_int_literal<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_int, |lint| {
|
||||||
let mut err = lint.build(fluent::lint::overflowing_int);
|
lint.set_arg("ty", t.name_str())
|
||||||
err.set_arg("ty", t.name_str());
|
.set_arg(
|
||||||
err.set_arg(
|
"lit",
|
||||||
"lit",
|
cx.sess()
|
||||||
cx.sess()
|
.source_map()
|
||||||
.source_map()
|
.span_to_snippet(lit.span)
|
||||||
.span_to_snippet(lit.span)
|
.expect("must get snippet from literal"),
|
||||||
.expect("must get snippet from literal"),
|
)
|
||||||
);
|
.set_arg("min", min)
|
||||||
err.set_arg("min", min);
|
.set_arg("max", max)
|
||||||
err.set_arg("max", max);
|
.note(fluent::lint::note);
|
||||||
err.note(fluent::lint::note);
|
|
||||||
if let Some(sugg_ty) =
|
if let Some(sugg_ty) =
|
||||||
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
|
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
|
||||||
{
|
{
|
||||||
err.set_arg("suggestion_ty", sugg_ty);
|
lint.set_arg("suggestion_ty", sugg_ty);
|
||||||
err.help(fluent::lint::help);
|
lint.help(fluent::lint::help);
|
||||||
}
|
}
|
||||||
err.emit();
|
|
||||||
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,16 +407,19 @@ fn lint_uint_literal<'tcx>(
|
|||||||
match par_e.kind {
|
match par_e.kind {
|
||||||
hir::ExprKind::Cast(..) => {
|
hir::ExprKind::Cast(..) => {
|
||||||
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
|
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::only_cast_u8_to_char)
|
OVERFLOWING_LITERALS,
|
||||||
.span_suggestion(
|
par_e.span,
|
||||||
|
fluent::lint::only_cast_u8_to_char,
|
||||||
|
|lint| {
|
||||||
|
lint.span_suggestion(
|
||||||
par_e.span,
|
par_e.span,
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
format!("'\\u{{{:X}}}'", lit_val),
|
format!("'\\u{{{:X}}}'", lit_val),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,9 +441,8 @@ fn lint_uint_literal<'tcx>(
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint::overflowing_uint, |lint| {
|
||||||
lint.build(fluent::lint::overflowing_uint)
|
lint.set_arg("ty", t.name_str())
|
||||||
.set_arg("ty", t.name_str())
|
|
||||||
.set_arg(
|
.set_arg(
|
||||||
"lit",
|
"lit",
|
||||||
cx.sess()
|
cx.sess()
|
||||||
@ -437,7 +453,6 @@ fn lint_uint_literal<'tcx>(
|
|||||||
.set_arg("min", min)
|
.set_arg("min", min)
|
||||||
.set_arg("max", max)
|
.set_arg("max", max)
|
||||||
.note(fluent::lint::note)
|
.note(fluent::lint::note)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,19 +482,22 @@ fn lint_literal<'tcx>(
|
|||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
if is_infinite == Ok(true) {
|
if is_infinite == Ok(true) {
|
||||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::overflowing_literal)
|
OVERFLOWING_LITERALS,
|
||||||
.set_arg("ty", t.name_str())
|
e.span,
|
||||||
.set_arg(
|
fluent::lint::overflowing_literal,
|
||||||
"lit",
|
|lint| {
|
||||||
cx.sess()
|
lint.set_arg("ty", t.name_str())
|
||||||
.source_map()
|
.set_arg(
|
||||||
.span_to_snippet(lit.span)
|
"lit",
|
||||||
.expect("must get snippet from literal"),
|
cx.sess()
|
||||||
)
|
.source_map()
|
||||||
.note(fluent::lint::note)
|
.span_to_snippet(lit.span)
|
||||||
.emit();
|
.expect("must get snippet from literal"),
|
||||||
});
|
)
|
||||||
|
.note(fluent::lint::note)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -497,9 +515,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
|||||||
}
|
}
|
||||||
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
hir::ExprKind::Binary(binop, ref l, ref r) => {
|
||||||
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
|
||||||
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::unused_comparisons).emit();
|
UNUSED_COMPARISONS,
|
||||||
});
|
e.span,
|
||||||
|
fluent::lint::unused_comparisons,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
|
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
|
||||||
@ -1150,25 +1171,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||||||
CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
|
CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.cx.struct_span_lint(lint, sp, |lint| {
|
self.cx.struct_span_lint(lint, sp, fluent::lint::improper_ctypes, |lint| {
|
||||||
let item_description = match self.mode {
|
let item_description = match self.mode {
|
||||||
CItemKind::Declaration => "block",
|
CItemKind::Declaration => "block",
|
||||||
CItemKind::Definition => "fn",
|
CItemKind::Definition => "fn",
|
||||||
};
|
};
|
||||||
let mut diag = lint.build(fluent::lint::improper_ctypes);
|
lint.set_arg("ty", ty);
|
||||||
diag.set_arg("ty", ty);
|
lint.set_arg("desc", item_description);
|
||||||
diag.set_arg("desc", item_description);
|
lint.span_label(sp, fluent::lint::label);
|
||||||
diag.span_label(sp, fluent::lint::label);
|
|
||||||
if let Some(help) = help {
|
if let Some(help) = help {
|
||||||
diag.help(help);
|
lint.help(help);
|
||||||
}
|
}
|
||||||
diag.note(note);
|
lint.note(note);
|
||||||
if let ty::Adt(def, _) = ty.kind() {
|
if let ty::Adt(def, _) = ty.kind() {
|
||||||
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
|
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
|
||||||
diag.span_note(sp, fluent::lint::note);
|
lint.span_note(sp, fluent::lint::note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diag.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1381,11 +1401,8 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
|
|||||||
cx.struct_span_lint(
|
cx.struct_span_lint(
|
||||||
VARIANT_SIZE_DIFFERENCES,
|
VARIANT_SIZE_DIFFERENCES,
|
||||||
enum_definition.variants[largest_index].span,
|
enum_definition.variants[largest_index].span,
|
||||||
|lint| {
|
fluent::lint::variant_size_differences,
|
||||||
lint.build(fluent::lint::variant_size_differences)
|
|lint| lint.set_arg("largest", largest),
|
||||||
.set_arg("largest", largest)
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1493,25 +1510,16 @@ impl InvalidAtomicOrdering {
|
|||||||
|
|
||||||
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
|
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
|
||||||
&& let Some((ordering_arg, invalid_ordering)) = match method {
|
&& let Some((ordering_arg, invalid_ordering, msg)) = match method {
|
||||||
sym::load => Some((&args[0], sym::Release)),
|
sym::load => Some((&args[0], sym::Release, fluent::lint::atomic_ordering_load)),
|
||||||
sym::store => Some((&args[1], sym::Acquire)),
|
sym::store => Some((&args[1], sym::Acquire, fluent::lint::atomic_ordering_store)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg)
|
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg)
|
||||||
&& (ordering == invalid_ordering || ordering == sym::AcqRel)
|
&& (ordering == invalid_ordering || ordering == sym::AcqRel)
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
|
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| {
|
||||||
if method == sym::load {
|
lint.help(fluent::lint::help)
|
||||||
diag.build(fluent::lint::atomic_ordering_load)
|
|
||||||
.help(fluent::lint::help)
|
|
||||||
.emit()
|
|
||||||
} else {
|
|
||||||
debug_assert_eq!(method, sym::store);
|
|
||||||
diag.build(fluent::lint::atomic_ordering_store)
|
|
||||||
.help(fluent::lint::help)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1523,10 +1531,9 @@ impl InvalidAtomicOrdering {
|
|||||||
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
|
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
|
||||||
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
|
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
|
||||||
{
|
{
|
||||||
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
|
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint::atomic_ordering_fence, |lint| {
|
||||||
diag.build(fluent::lint::atomic_ordering_fence)
|
lint
|
||||||
.help(fluent::lint::help)
|
.help(fluent::lint::help)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,9 +154,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(must_use_op) = must_use_op {
|
if let Some(must_use_op) = must_use_op {
|
||||||
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| {
|
cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint::unused_op, |lint| {
|
||||||
lint.build(fluent::lint::unused_op)
|
lint.set_arg("op", must_use_op)
|
||||||
.set_arg("op", must_use_op)
|
|
||||||
.span_label(expr.span, fluent::lint::label)
|
.span_label(expr.span, fluent::lint::label)
|
||||||
.span_suggestion_verbose(
|
.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_lo(),
|
expr.span.shrink_to_lo(),
|
||||||
@ -164,14 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
"let _ = ",
|
"let _ = ",
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
op_warned = true;
|
op_warned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
if !(type_permits_lack_of_use || fn_warned || op_warned) {
|
||||||
cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
|
cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint::unused_result, |lint| {
|
||||||
lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit();
|
lint.set_arg("ty", ty)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,29 +265,35 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ty::Closure(..) => {
|
ty::Closure(..) => {
|
||||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
cx.struct_span_lint(
|
||||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
UNUSED_MUST_USE,
|
||||||
// pre/post strings
|
span,
|
||||||
lint.build(fluent::lint::unused_closure)
|
fluent::lint::unused_closure,
|
||||||
.set_arg("count", plural_len)
|
|lint| {
|
||||||
.set_arg("pre", descr_pre)
|
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||||
.set_arg("post", descr_post)
|
// pre/post strings
|
||||||
.note(fluent::lint::note)
|
lint.set_arg("count", plural_len)
|
||||||
.emit();
|
.set_arg("pre", descr_pre)
|
||||||
});
|
.set_arg("post", descr_post)
|
||||||
|
.note(fluent::lint::note)
|
||||||
|
},
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ty::Generator(..) => {
|
ty::Generator(..) => {
|
||||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
cx.struct_span_lint(
|
||||||
// FIXME(davidtwco): this isn't properly translatable because of the
|
UNUSED_MUST_USE,
|
||||||
// pre/post strings
|
span,
|
||||||
lint.build(fluent::lint::unused_generator)
|
fluent::lint::unused_generator,
|
||||||
.set_arg("count", plural_len)
|
|lint| {
|
||||||
.set_arg("pre", descr_pre)
|
// FIXME(davidtwco): this isn't properly translatable because of the
|
||||||
.set_arg("post", descr_post)
|
// pre/post strings
|
||||||
.note(fluent::lint::note)
|
lint.set_arg("count", plural_len)
|
||||||
.emit();
|
.set_arg("pre", descr_pre)
|
||||||
});
|
.set_arg("post", descr_post)
|
||||||
|
.note(fluent::lint::note)
|
||||||
|
},
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -309,18 +313,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
descr_post_path: &str,
|
descr_post_path: &str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
|
||||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint::unused_def, |lint| {
|
||||||
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
|
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
|
||||||
// strings
|
// strings
|
||||||
let mut err = lint.build(fluent::lint::unused_def);
|
lint.set_arg("pre", descr_pre_path);
|
||||||
err.set_arg("pre", descr_pre_path);
|
lint.set_arg("post", descr_post_path);
|
||||||
err.set_arg("post", descr_post_path);
|
lint.set_arg("def", cx.tcx.def_path_str(def_id));
|
||||||
err.set_arg("def", cx.tcx.def_path_str(def_id));
|
|
||||||
// check for #[must_use = "..."]
|
// check for #[must_use = "..."]
|
||||||
if let Some(note) = attr.value_str() {
|
if let Some(note) = attr.value_str() {
|
||||||
err.note(note.as_str());
|
lint.note(note.as_str());
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -357,25 +360,34 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
|||||||
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
|
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
|
||||||
if let hir::StmtKind::Semi(expr) = s.kind {
|
if let hir::StmtKind::Semi(expr) = s.kind {
|
||||||
if let hir::ExprKind::Path(_) = expr.kind {
|
if let hir::ExprKind::Path(_) = expr.kind {
|
||||||
cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| {
|
let ty = cx.typeck_results().expr_ty(expr);
|
||||||
let ty = cx.typeck_results().expr_ty(expr);
|
if ty.needs_drop(cx.tcx, cx.param_env) {
|
||||||
if ty.needs_drop(cx.tcx, cx.param_env) {
|
cx.struct_span_lint(
|
||||||
let mut lint = lint.build(fluent::lint::path_statement_drop);
|
PATH_STATEMENTS,
|
||||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
s.span,
|
||||||
lint.span_suggestion(
|
fluent::lint::path_statement_drop,
|
||||||
s.span,
|
|lint| {
|
||||||
fluent::lint::suggestion,
|
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
||||||
format!("drop({});", snippet),
|
lint.span_suggestion(
|
||||||
Applicability::MachineApplicable,
|
s.span,
|
||||||
);
|
fluent::lint::suggestion,
|
||||||
} else {
|
format!("drop({});", snippet),
|
||||||
lint.span_help(s.span, fluent::lint::suggestion);
|
Applicability::MachineApplicable,
|
||||||
}
|
);
|
||||||
lint.emit();
|
} else {
|
||||||
} else {
|
lint.span_help(s.span, fluent::lint::suggestion);
|
||||||
lint.build(fluent::lint::path_statement_no_effect).emit();
|
}
|
||||||
}
|
lint
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cx.struct_span_lint(
|
||||||
|
PATH_STATEMENTS,
|
||||||
|
s.span,
|
||||||
|
fluent::lint::path_statement_no_effect,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,22 +557,21 @@ trait UnusedDelimLint {
|
|||||||
} else {
|
} else {
|
||||||
MultiSpan::from(value_span)
|
MultiSpan::from(value_span)
|
||||||
};
|
};
|
||||||
cx.struct_span_lint(self.lint(), primary_span, |lint| {
|
cx.struct_span_lint(self.lint(), primary_span, fluent::lint::unused_delim, |lint| {
|
||||||
let mut db = lint.build(fluent::lint::unused_delim);
|
lint.set_arg("delim", Self::DELIM_STR);
|
||||||
db.set_arg("delim", Self::DELIM_STR);
|
lint.set_arg("item", msg);
|
||||||
db.set_arg("item", msg);
|
|
||||||
if let Some((lo, hi)) = spans {
|
if let Some((lo, hi)) = spans {
|
||||||
let replacement = vec![
|
let replacement = vec![
|
||||||
(lo, if keep_space.0 { " ".into() } else { "".into() }),
|
(lo, if keep_space.0 { " ".into() } else { "".into() }),
|
||||||
(hi, if keep_space.1 { " ".into() } else { "".into() }),
|
(hi, if keep_space.1 { " ".into() } else { "".into() }),
|
||||||
];
|
];
|
||||||
db.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
replacement,
|
replacement,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
db.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,9 +1139,12 @@ impl UnusedImportBraces {
|
|||||||
ast::UseTreeKind::Nested(_) => return,
|
ast::UseTreeKind::Nested(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit();
|
UNUSED_IMPORT_BRACES,
|
||||||
});
|
item.span,
|
||||||
|
fluent::lint::unused_import_braces,
|
||||||
|
|lint| lint.set_arg("node", node_name),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1179,15 +1193,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
|||||||
|
|
||||||
for adj in cx.typeck_results().expr_adjustments(e) {
|
for adj in cx.typeck_results().expr_adjustments(e) {
|
||||||
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
||||||
cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| {
|
cx.struct_span_lint(
|
||||||
lint.build(match m {
|
UNUSED_ALLOCATION,
|
||||||
|
e.span,
|
||||||
|
match m {
|
||||||
adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
|
adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
|
||||||
adjustment::AutoBorrowMutability::Mut { .. } => {
|
adjustment::AutoBorrowMutability::Mut { .. } => {
|
||||||
fluent::lint::unused_allocation_mut
|
fluent::lint::unused_allocation_mut
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
.emit();
|
|lint| lint,
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,38 +96,43 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||||||
let body = builder.body(&variant);
|
let body = builder.body(&variant);
|
||||||
|
|
||||||
let diag = &builder.parent.diag;
|
let diag = &builder.parent.diag;
|
||||||
let init = match builder.slug.value_ref() {
|
|
||||||
|
quote! {
|
||||||
|
#preamble
|
||||||
|
#body
|
||||||
|
#diag
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let msg = builder.each_variant(&mut structure, |mut builder, variant| {
|
||||||
|
// HACK(wafflelapkin): initialize slug (???)
|
||||||
|
let _preamble = builder.preamble(&variant);
|
||||||
|
|
||||||
|
match builder.slug.value_ref() {
|
||||||
None => {
|
None => {
|
||||||
span_err(builder.span, "diagnostic slug not specified")
|
span_err(builder.span, "diagnostic slug not specified")
|
||||||
.help(&format!(
|
.help(&format!(
|
||||||
"specify the slug as the first argument to the attribute, such as \
|
"specify the slug as the first argument to the attribute, such as \
|
||||||
`#[diag(typeck::example_error)]`",
|
`#[diag(typeck::example_error)]`",
|
||||||
))
|
))
|
||||||
.emit();
|
.emit();
|
||||||
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
}
|
}
|
||||||
Some(slug) => {
|
Some(slug) => quote! { rustc_errors::fluent::#slug.into() },
|
||||||
quote! {
|
|
||||||
let mut #diag = #diag.build(rustc_errors::fluent::#slug);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#init
|
|
||||||
#preamble
|
|
||||||
#body
|
|
||||||
#diag.emit();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let diag = &builder.diag;
|
let diag = &builder.diag;
|
||||||
structure.gen_impl(quote! {
|
structure.gen_impl(quote! {
|
||||||
gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self {
|
gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self {
|
||||||
fn decorate_lint(self, #diag: rustc_errors::LintDiagnosticBuilder<'__a, ()>) {
|
fn decorate_lint<'__b>(self, #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()>) -> &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> {
|
||||||
use rustc_errors::IntoDiagnosticArg;
|
use rustc_errors::IntoDiagnosticArg;
|
||||||
#implementation
|
#implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn msg(&self) -> rustc_errors::DiagnosticMessage {
|
||||||
|
#msg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::cmp;
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan};
|
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
@ -283,7 +283,11 @@ pub fn struct_lint_level<'s, 'd>(
|
|||||||
level: Level,
|
level: Level,
|
||||||
src: LintLevelSource,
|
src: LintLevelSource,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl 'd
|
||||||
|
+ for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
||||||
// the "real" work.
|
// the "real" work.
|
||||||
@ -293,7 +297,13 @@ pub fn struct_lint_level<'s, 'd>(
|
|||||||
level: Level,
|
level: Level,
|
||||||
src: LintLevelSource,
|
src: LintLevelSource,
|
||||||
span: Option<MultiSpan>,
|
span: Option<MultiSpan>,
|
||||||
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: Box<
|
||||||
|
dyn 'd
|
||||||
|
+ for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
// Check for future incompatibility lints and issue a stronger warning.
|
// Check for future incompatibility lints and issue a stronger warning.
|
||||||
let future_incompatible = lint.future_incompatible;
|
let future_incompatible = lint.future_incompatible;
|
||||||
@ -344,6 +354,9 @@ pub fn struct_lint_level<'s, 'd>(
|
|||||||
(Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
|
(Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
err.set_primary_message(msg);
|
||||||
|
err.set_is_lint();
|
||||||
|
|
||||||
// If this code originates in a foreign macro, aka something that this crate
|
// If this code originates in a foreign macro, aka something that this crate
|
||||||
// did not itself author, then it's likely that there's nothing this crate
|
// did not itself author, then it's likely that there's nothing this crate
|
||||||
// can do about it. We probably want to skip the lint entirely.
|
// can do about it. We probably want to skip the lint entirely.
|
||||||
@ -373,12 +386,12 @@ pub fn struct_lint_level<'s, 'd>(
|
|||||||
if let Level::Expect(_) = level {
|
if let Level::Expect(_) = level {
|
||||||
let name = lint.name_lower();
|
let name = lint.name_lower();
|
||||||
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
|
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
|
||||||
decorate(LintDiagnosticBuilder::new(err));
|
|
||||||
|
decorate(&mut err);
|
||||||
|
err.emit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
explain_lint_level_source(lint, level, src, &mut err);
|
|
||||||
|
|
||||||
let name = lint.name_lower();
|
let name = lint.name_lower();
|
||||||
let is_force_warn = matches!(level, Level::ForceWarn(_));
|
let is_force_warn = matches!(level, Level::ForceWarn(_));
|
||||||
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
|
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
|
||||||
@ -417,10 +430,12 @@ pub fn struct_lint_level<'s, 'd>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
|
// Finally, run `decorate`.
|
||||||
decorate(LintDiagnosticBuilder::new(err));
|
decorate(&mut err);
|
||||||
|
explain_lint_level_source(lint, level, src, &mut *err);
|
||||||
|
err.emit()
|
||||||
}
|
}
|
||||||
struct_lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
|
struct_lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether `span` originates in a foreign crate's external macro.
|
/// Returns whether `span` originates in a foreign crate's external macro.
|
||||||
|
@ -253,13 +253,12 @@ fn late_report_deprecation(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let method_span = method_span.unwrap_or(span);
|
let method_span = method_span.unwrap_or(span);
|
||||||
tcx.struct_span_lint_hir(lint, hir_id, method_span, |lint| {
|
tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
|
||||||
let mut diag = lint.build(message);
|
|
||||||
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
|
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
|
||||||
let kind = tcx.def_kind(def_id).descr(def_id);
|
let kind = tcx.def_kind(def_id).descr(def_id);
|
||||||
deprecation_suggestion(&mut diag, kind, suggestion, method_span);
|
deprecation_suggestion(diag, kind, suggestion, method_span);
|
||||||
}
|
}
|
||||||
diag.emit();
|
diag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,9 +620,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
unmarked: impl FnOnce(Span, DefId),
|
unmarked: impl FnOnce(Span, DefId),
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let soft_handler = |lint, span, msg: &_| {
|
let soft_handler = |lint, span, msg: &_| {
|
||||||
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
|
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
|
||||||
lint.build(msg).emit();
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
let eval_result =
|
let eval_result =
|
||||||
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
|
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
|
||||||
|
@ -35,7 +35,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|||||||
use rustc_data_structures::steal::Steal;
|
use rustc_data_structures::steal::Steal;
|
||||||
use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
|
use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
|
||||||
use rustc_data_structures::vec_map::VecMap;
|
use rustc_data_structures::vec_map::VecMap;
|
||||||
use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan};
|
use rustc_errors::{
|
||||||
|
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||||
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
||||||
@ -2857,7 +2859,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
span: impl Into<MultiSpan>,
|
span: impl Into<MultiSpan>,
|
||||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag))
|
self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| {
|
||||||
|
decorator.decorate_lint(diag)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn struct_span_lint_hir(
|
pub fn struct_span_lint_hir(
|
||||||
@ -2865,10 +2869,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
span: impl Into<MultiSpan>,
|
span: impl Into<MultiSpan>,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
||||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
|
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
||||||
@ -2879,17 +2886,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
id: HirId,
|
id: HirId,
|
||||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||||
) {
|
) {
|
||||||
self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag))
|
self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn struct_lint_node(
|
pub fn struct_lint_node(
|
||||||
self,
|
self,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
id: HirId,
|
id: HirId,
|
||||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'b mut DiagnosticBuilder<'a, ()>,
|
||||||
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||||
) {
|
) {
|
||||||
let (level, src) = self.lint_level_at_node(lint, id);
|
let (level, src) = self.lint_level_at_node(lint, id);
|
||||||
struct_lint_level(self.sess, lint, level, src, None, decorate);
|
struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
|
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
|
||||||
|
@ -89,15 +89,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
UNSAFE_OP_IN_UNSAFE_FN,
|
||||||
self.hir_context,
|
self.hir_context,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
format!("{} is unsafe and requires unsafe block (error E0133)", description,),
|
||||||
lint.build(&format!(
|
|lint| lint.span_label(span, kind.simple_description()).note(note),
|
||||||
"{} is unsafe and requires unsafe block (error E0133)",
|
|
||||||
description,
|
|
||||||
))
|
|
||||||
.span_label(span, kind.simple_description())
|
|
||||||
.note(note)
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SafetyContext::Safe => {
|
SafetyContext::Safe => {
|
||||||
@ -125,14 +118,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||||||
enclosing_unsafe: Option<(Span, &'static str)>,
|
enclosing_unsafe: Option<(Span, &'static str)>,
|
||||||
) {
|
) {
|
||||||
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
|
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
|
||||||
self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, |lint| {
|
let msg = "unnecessary `unsafe` block";
|
||||||
let msg = "unnecessary `unsafe` block";
|
self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| {
|
||||||
let mut db = lint.build(msg);
|
lint.span_label(block_span, msg);
|
||||||
db.span_label(block_span, msg);
|
|
||||||
if let Some((span, kind)) = enclosing_unsafe {
|
if let Some((span, kind)) = enclosing_unsafe {
|
||||||
db.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
|
lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
|
||||||
}
|
}
|
||||||
db.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,16 +36,20 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
|||||||
|
|
||||||
let sp = tcx.def_span(def_id);
|
let sp = tcx.def_span(def_id);
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
let mut db = lint.build("function cannot return without recursing");
|
UNCONDITIONAL_RECURSION,
|
||||||
db.span_label(sp, "cannot return without recursing");
|
hir_id,
|
||||||
// offer some help to the programmer.
|
sp,
|
||||||
for call_span in vis.reachable_recursive_calls {
|
"function cannot return without recursing",
|
||||||
db.span_label(call_span, "recursive call site");
|
|lint| {
|
||||||
}
|
lint.span_label(sp, "cannot return without recursing");
|
||||||
db.help("a `loop` may express intention better if this is on purpose");
|
// offer some help to the programmer.
|
||||||
db.emit();
|
for call_span in vis.reachable_recursive_calls {
|
||||||
});
|
lint.span_label(call_span, "recursive call site");
|
||||||
|
}
|
||||||
|
lint.help("a `loop` may express intention better if this is on purpose")
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use super::{PatCtxt, PatternError};
|
|||||||
use rustc_arena::TypedArena;
|
use rustc_arena::TypedArena;
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
|
error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder,
|
||||||
ErrorGuaranteed, MultiSpan,
|
ErrorGuaranteed, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -347,19 +347,23 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
let span_end = affix.last().unwrap().unwrap().0;
|
let span_end = affix.last().unwrap().unwrap().0;
|
||||||
let span = span_start.to(span_end);
|
let span = span_start.to(span_end);
|
||||||
let cnt = affix.len();
|
let cnt = affix.len();
|
||||||
cx.tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, top, span, |lint| {
|
let s = pluralize!(cnt);
|
||||||
let s = pluralize!(cnt);
|
cx.tcx.struct_span_lint_hir(
|
||||||
let mut diag = lint.build(&format!("{kind} irrefutable pattern{s} in let chain"));
|
IRREFUTABLE_LET_PATTERNS,
|
||||||
diag.note(&format!(
|
top,
|
||||||
"{these} pattern{s} will always match",
|
span,
|
||||||
these = pluralize!("this", cnt),
|
format!("{kind} irrefutable pattern{s} in let chain"),
|
||||||
));
|
|lint| {
|
||||||
diag.help(&format!(
|
lint.note(format!(
|
||||||
"consider moving {} {suggestion}",
|
"{these} pattern{s} will always match",
|
||||||
if cnt > 1 { "them" } else { "it" }
|
these = pluralize!("this", cnt),
|
||||||
));
|
))
|
||||||
diag.emit()
|
.help(format!(
|
||||||
});
|
"consider moving {} {suggestion}",
|
||||||
|
if cnt > 1 { "them" } else { "it" }
|
||||||
|
))
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
|
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
|
||||||
// The chain has a non-zero prefix of irrefutable `let` statements.
|
// The chain has a non-zero prefix of irrefutable `let` statements.
|
||||||
@ -561,26 +565,28 @@ fn check_for_bindings_named_same_as_variants(
|
|||||||
BINDINGS_WITH_VARIANT_NAME,
|
BINDINGS_WITH_VARIANT_NAME,
|
||||||
p.hir_id,
|
p.hir_id,
|
||||||
p.span,
|
p.span,
|
||||||
|
DelayDm(|| format!(
|
||||||
|
"pattern binding `{}` is named the same as one \
|
||||||
|
of the variants of the type `{}`",
|
||||||
|
ident, cx.tcx.def_path_str(edef.did())
|
||||||
|
)),
|
||||||
|lint| {
|
|lint| {
|
||||||
let ty_path = cx.tcx.def_path_str(edef.did());
|
let ty_path = cx.tcx.def_path_str(edef.did());
|
||||||
let mut err = lint.build(&format!(
|
lint.code(error_code!(E0170));
|
||||||
"pattern binding `{}` is named the same as one \
|
|
||||||
of the variants of the type `{}`",
|
|
||||||
ident, ty_path
|
|
||||||
));
|
|
||||||
err.code(error_code!(E0170));
|
|
||||||
// If this is an irrefutable pattern, and there's > 1 variant,
|
// If this is an irrefutable pattern, and there's > 1 variant,
|
||||||
// then we can't actually match on this. Applying the below
|
// then we can't actually match on this. Applying the below
|
||||||
// suggestion would produce code that breaks on `check_irrefutable`.
|
// suggestion would produce code that breaks on `check_irrefutable`.
|
||||||
if rf == Refutable || variant_count == 1 {
|
if rf == Refutable || variant_count == 1 {
|
||||||
err.span_suggestion(
|
lint.span_suggestion(
|
||||||
p.span,
|
p.span,
|
||||||
"to match on the variant, qualify the path",
|
"to match on the variant, qualify the path",
|
||||||
format!("{}::{}", ty_path, ident),
|
format!("{}::{}", ty_path, ident),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.emit();
|
|
||||||
|
lint
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -598,14 +604,13 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
|
fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
|
||||||
tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, |lint| {
|
tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| {
|
||||||
let mut err = lint.build("unreachable pattern");
|
|
||||||
if let Some(catchall) = catchall {
|
if let Some(catchall) = catchall {
|
||||||
// We had a catchall pattern, hint at that.
|
// We had a catchall pattern, hint at that.
|
||||||
err.span_label(span, "unreachable pattern");
|
lint.span_label(span, "unreachable pattern");
|
||||||
err.span_label(catchall, "matches any value");
|
lint.span_label(catchall, "matches any value");
|
||||||
}
|
}
|
||||||
err.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,6 +626,11 @@ fn irrefutable_let_patterns(
|
|||||||
count: usize,
|
count: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
|
let span = match source {
|
||||||
|
LetSource::LetElse(span) => span,
|
||||||
|
_ => span,
|
||||||
|
};
|
||||||
|
|
||||||
macro_rules! emit_diag {
|
macro_rules! emit_diag {
|
||||||
(
|
(
|
||||||
$lint:expr,
|
$lint:expr,
|
||||||
@ -630,18 +640,23 @@ fn irrefutable_let_patterns(
|
|||||||
) => {{
|
) => {{
|
||||||
let s = pluralize!(count);
|
let s = pluralize!(count);
|
||||||
let these = pluralize!("this", count);
|
let these = pluralize!("this", count);
|
||||||
let mut diag = $lint.build(&format!("irrefutable {} pattern{s}", $source_name));
|
tcx.struct_span_lint_hir(
|
||||||
diag.note(&format!("{these} pattern{s} will always match, so the {}", $note_sufix));
|
IRREFUTABLE_LET_PATTERNS,
|
||||||
diag.help(concat!("consider ", $help_sufix));
|
id,
|
||||||
diag.emit()
|
span,
|
||||||
|
format!("irrefutable {} pattern{s}", $source_name),
|
||||||
|
|lint| {
|
||||||
|
lint.note(&format!(
|
||||||
|
"{these} pattern{s} will always match, so the {}",
|
||||||
|
$note_sufix
|
||||||
|
))
|
||||||
|
.help(concat!("consider ", $help_sufix))
|
||||||
|
},
|
||||||
|
)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = match source {
|
match source {
|
||||||
LetSource::LetElse(span) => span,
|
|
||||||
_ => span,
|
|
||||||
};
|
|
||||||
tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
|
|
||||||
LetSource::GenericLet => {
|
LetSource::GenericLet => {
|
||||||
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
|
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
|
||||||
}
|
}
|
||||||
@ -677,7 +692,7 @@ fn irrefutable_let_patterns(
|
|||||||
"instead using a `loop { ... }` with a `let` inside it"
|
"instead using a `loop { ... }` with a `let` inside it"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_let_irrefutable<'p, 'tcx>(
|
fn is_let_irrefutable<'p, 'tcx>(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use rustc_errors::DelayDm;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
@ -205,9 +206,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
self.id,
|
self.id,
|
||||||
self.span,
|
self.span,
|
||||||
|lint| {
|
msg,
|
||||||
lint.build(&msg).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
@ -286,9 +286,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
"floating-point types cannot be used in patterns",
|
||||||
lint.build("floating-point types cannot be used in patterns").emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
@ -340,15 +339,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
DelayDm(|| {
|
||||||
let msg = format!(
|
format!(
|
||||||
"to use a constant of type `{}` in a pattern, \
|
"to use a constant of type `{}` in a pattern, \
|
||||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||||
cv.ty(),
|
cv.ty(),
|
||||||
cv.ty(),
|
cv.ty(),
|
||||||
);
|
)
|
||||||
lint.build(&msg).emit();
|
}),
|
||||||
},
|
|lint| lint,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Since we are behind a reference, we can just bubble the error up so we get a
|
// Since we are behind a reference, we can just bubble the error up so we get a
|
||||||
@ -488,7 +487,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
self.id,
|
self.id,
|
||||||
self.span,
|
self.span,
|
||||||
|lint| {lint.build(&msg).emit();},
|
msg,
|
||||||
|
|lint| lint,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
@ -556,9 +556,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
msg,
|
||||||
lint.build(msg).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Constant { value: cv }
|
PatKind::Constant { value: cv }
|
||||||
@ -594,9 +593,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||||||
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| {
|
msg,
|
||||||
lint.build(&msg).emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,10 +299,10 @@ impl IntRange {
|
|||||||
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
|
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
|
||||||
hir_id,
|
hir_id,
|
||||||
pcx.span,
|
pcx.span,
|
||||||
|
"multiple patterns overlap on their endpoints",
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build("multiple patterns overlap on their endpoints");
|
|
||||||
for (int_range, span) in overlaps {
|
for (int_range, span) in overlaps {
|
||||||
err.span_label(
|
lint.span_label(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
"this range overlaps on `{}`...",
|
"this range overlaps on `{}`...",
|
||||||
@ -310,9 +310,9 @@ impl IntRange {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
err.span_label(pcx.span, "... with this range");
|
lint.span_label(pcx.span, "... with this range");
|
||||||
err.note("you likely meant to write mutually exclusive ranges");
|
lint.note("you likely meant to write mutually exclusive ranges");
|
||||||
err.emit();
|
lint
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -754,9 +754,8 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
|
|||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
|
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
|
||||||
) {
|
) {
|
||||||
cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| {
|
cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, "some variants are not matched explicitly", |lint| {
|
||||||
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
|
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
|
||||||
let mut lint = build.build("some variants are not matched explicitly");
|
|
||||||
lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
|
lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
|
||||||
lint.help(
|
lint.help(
|
||||||
"ensure that all variants are matched explicitly by adding the suggested match arms",
|
"ensure that all variants are matched explicitly by adding the suggested match arms",
|
||||||
@ -765,7 +764,7 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
|
|||||||
"the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
"the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
||||||
scrut_ty,
|
scrut_ty,
|
||||||
));
|
));
|
||||||
lint.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rustc_errors::{DiagnosticBuilder, LintDiagnosticBuilder};
|
use rustc_errors::{DiagnosticBuilder, DiagnosticMessage};
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
@ -63,7 +63,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
|||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
const_item: DefId,
|
const_item: DefId,
|
||||||
location: Location,
|
location: Location,
|
||||||
decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
decorate: impl for<'a, 'b> FnOnce(
|
||||||
|
&'a mut DiagnosticBuilder<'b, ()>,
|
||||||
|
) -> &'a mut DiagnosticBuilder<'b, ()>,
|
||||||
) {
|
) {
|
||||||
// Don't lint on borrowing/assigning when a dereference is involved.
|
// Don't lint on borrowing/assigning when a dereference is involved.
|
||||||
// If we 'leave' the temporary via a dereference, we must
|
// If we 'leave' the temporary via a dereference, we must
|
||||||
@ -84,10 +87,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
|||||||
CONST_ITEM_MUTATION,
|
CONST_ITEM_MUTATION,
|
||||||
lint_root,
|
lint_root,
|
||||||
source_info.span,
|
source_info.span,
|
||||||
|
msg,
|
||||||
|lint| {
|
|lint| {
|
||||||
decorate(lint)
|
decorate(lint)
|
||||||
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
|
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -102,10 +105,8 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
|
|||||||
// so emitting a lint would be redundant.
|
// so emitting a lint would be redundant.
|
||||||
if !lhs.projection.is_empty() {
|
if !lhs.projection.is_empty() {
|
||||||
if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) {
|
if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) {
|
||||||
self.lint_const_item_usage(&lhs, def_id, loc, |lint| {
|
self.lint_const_item_usage(&lhs, def_id, loc, "attempting to modify a `const` item",|lint| {
|
||||||
let mut lint = lint.build("attempting to modify a `const` item");
|
lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified")
|
||||||
lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified");
|
|
||||||
lint
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,8 +138,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
|
|||||||
});
|
});
|
||||||
let lint_loc =
|
let lint_loc =
|
||||||
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
|
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
|
||||||
self.lint_const_item_usage(place, def_id, lint_loc, |lint| {
|
self.lint_const_item_usage(place, def_id, lint_loc, "taking a mutable reference to a `const` item", |lint| {
|
||||||
let mut lint = lint.build("taking a mutable reference to a `const` item");
|
|
||||||
lint
|
lint
|
||||||
.note("each usage of a `const` item creates a new temporary")
|
.note("each usage of a `const` item creates a new temporary")
|
||||||
.note("the mutable reference will refer to this temporary, not the original `const` item");
|
.note("the mutable reference will refer to this temporary, not the original `const` item");
|
||||||
|
@ -33,21 +33,27 @@ struct PackedRefChecker<'a, 'tcx> {
|
|||||||
fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
|
||||||
tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| {
|
// FIXME: when we make this a hard error, this should have its
|
||||||
// FIXME: when we make this a hard error, this should have its
|
// own error code.
|
||||||
// own error code.
|
|
||||||
let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
|
let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
|
||||||
"with type or const parameters"
|
"with type or const parameters"
|
||||||
} else {
|
} else {
|
||||||
"that does not derive `Copy`"
|
"that does not derive `Copy`"
|
||||||
};
|
};
|
||||||
let message = format!(
|
let message = format!(
|
||||||
"`{}` can't be derived on this `#[repr(packed)]` struct {}",
|
"`{}` can't be derived on this `#[repr(packed)]` struct {}",
|
||||||
tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
|
tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
|
||||||
extra
|
extra
|
||||||
);
|
);
|
||||||
lint.build(message).emit();
|
|
||||||
});
|
tcx.struct_span_lint_hir(
|
||||||
|
UNALIGNED_REFERENCES,
|
||||||
|
lint_hir_id,
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
message,
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
||||||
@ -86,8 +92,9 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
|||||||
UNALIGNED_REFERENCES,
|
UNALIGNED_REFERENCES,
|
||||||
lint_root,
|
lint_root,
|
||||||
source_info.span,
|
source_info.span,
|
||||||
|
"reference to packed field is unaligned",
|
||||||
|lint| {
|
|lint| {
|
||||||
lint.build("reference to packed field is unaligned")
|
lint
|
||||||
.note(
|
.note(
|
||||||
"fields of packed structs are not properly aligned, and creating \
|
"fields of packed structs are not properly aligned, and creating \
|
||||||
a misaligned reference is undefined behavior (even if that \
|
a misaligned reference is undefined behavior (even if that \
|
||||||
@ -98,7 +105,6 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
|
|||||||
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
|
||||||
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
(loads and stores via `*p` must be properly aligned even when using raw pointers)"
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -489,21 +489,20 @@ fn unsafety_check_result<'tcx>(
|
|||||||
|
|
||||||
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
|
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
|
||||||
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
|
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
|
||||||
tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| {
|
let msg = "unnecessary `unsafe` block";
|
||||||
let msg = "unnecessary `unsafe` block";
|
tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, msg, |lint| {
|
||||||
let mut db = lint.build(msg);
|
lint.span_label(span, msg);
|
||||||
db.span_label(span, msg);
|
|
||||||
match kind {
|
match kind {
|
||||||
UnusedUnsafe::Unused => {}
|
UnusedUnsafe::Unused => {}
|
||||||
UnusedUnsafe::InUnsafeBlock(id) => {
|
UnusedUnsafe::InUnsafeBlock(id) => {
|
||||||
db.span_label(
|
lint.span_label(
|
||||||
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
|
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
|
||||||
"because it's nested under this `unsafe` block",
|
"because it's nested under this `unsafe` block",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,15 +542,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
UNSAFE_OP_IN_UNSAFE_FN,
|
||||||
lint_root,
|
lint_root,
|
||||||
source_info.span,
|
source_info.span,
|
||||||
|lint| {
|
format!("{} is unsafe and requires unsafe block (error E0133)", description,),
|
||||||
lint.build(&format!(
|
|lint| lint.span_label(source_info.span, description).note(note),
|
||||||
"{} is unsafe and requires unsafe block (error E0133)",
|
|
||||||
description,
|
|
||||||
))
|
|
||||||
.span_label(source_info.span, description)
|
|
||||||
.note(note)
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,10 +347,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||||||
panic: AssertKind<impl std::fmt::Debug>,
|
panic: AssertKind<impl std::fmt::Debug>,
|
||||||
) {
|
) {
|
||||||
if let Some(lint_root) = self.lint_root(source_info) {
|
if let Some(lint_root) = self.lint_root(source_info) {
|
||||||
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, message, |lint| {
|
||||||
let mut err = lint.build(message);
|
lint.span_label(source_info.span, format!("{:?}", panic))
|
||||||
err.span_label(source_info.span, format!("{:?}", panic));
|
|
||||||
err.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,12 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
|
|||||||
.lint_root;
|
.lint_root;
|
||||||
let span = terminator.source_info.span;
|
let span = terminator.source_info.span;
|
||||||
|
|
||||||
tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, |lint| {
|
let msg = match fn_def_id {
|
||||||
let msg = match fn_def_id {
|
Some(_) => "call to foreign function with FFI-unwind ABI",
|
||||||
Some(_) => "call to foreign function with FFI-unwind ABI",
|
None => "call to function pointer with FFI-unwind ABI",
|
||||||
None => "call to function pointer with FFI-unwind ABI",
|
};
|
||||||
};
|
tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, msg, |lint| {
|
||||||
let mut db = lint.build(msg);
|
lint.span_label(span, msg)
|
||||||
db.span_label(span, msg);
|
|
||||||
db.emit();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
tainted = true;
|
tainted = true;
|
||||||
|
@ -179,11 +179,15 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||||||
let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
|
let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
|
||||||
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
|
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
|
||||||
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
|
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
|
||||||
self.tcx.struct_span_lint_hir(FUNCTION_ITEM_REFERENCES, lint_root, span, |lint| {
|
self.tcx.struct_span_lint_hir(
|
||||||
lint.build("taking a reference to a function item does not give a function pointer")
|
FUNCTION_ITEM_REFERENCES,
|
||||||
.span_suggestion(
|
lint_root,
|
||||||
|
span,
|
||||||
|
"taking a reference to a function item does not give a function pointer",
|
||||||
|
|lint| {
|
||||||
|
lint.span_suggestion(
|
||||||
span,
|
span,
|
||||||
&format!("cast `{}` to obtain a function pointer", ident),
|
format!("cast `{}` to obtain a function pointer", ident),
|
||||||
format!(
|
format!(
|
||||||
"{} as {}{}fn({}{}){}",
|
"{} as {}{}fn({}{}){}",
|
||||||
if params.is_empty() { ident } else { format!("{}::<{}>", ident, params) },
|
if params.is_empty() { ident } else { format!("{}::<{}>", ident, params) },
|
||||||
@ -195,7 +199,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||||||
),
|
),
|
||||||
Applicability::Unspecified,
|
Applicability::Unspecified,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,10 +370,13 @@ impl CheckAttrVisitor<'_> {
|
|||||||
b.push_str(&(allowed_target.to_string() + "s"));
|
b.push_str(&(allowed_target.to_string() + "s"));
|
||||||
b
|
b
|
||||||
});
|
});
|
||||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
self.tcx.struct_span_lint_hir(
|
||||||
lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
|
UNUSED_ATTRIBUTES,
|
||||||
.emit();
|
hir_id,
|
||||||
});
|
attr.span,
|
||||||
|
&format!("`#[{name}]` only has an effect on {}", supported_names),
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,25 +880,31 @@ impl CheckAttrVisitor<'_> {
|
|||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if hir_id != CRATE_HIR_ID {
|
if hir_id != CRATE_HIR_ID {
|
||||||
self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| {
|
self.tcx.struct_span_lint_hir(
|
||||||
let mut err = lint.build(fluent::passes::attr_crate_level);
|
INVALID_DOC_ATTRIBUTES,
|
||||||
if attr.style == AttrStyle::Outer
|
hir_id,
|
||||||
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
|
meta.span(),
|
||||||
{
|
fluent::passes::attr_crate_level,
|
||||||
if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
|
|err| {
|
||||||
src.insert(1, '!');
|
if attr.style == AttrStyle::Outer
|
||||||
err.span_suggestion_verbose(
|
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
|
||||||
attr.span,
|
{
|
||||||
fluent::passes::suggestion,
|
if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
|
||||||
src,
|
src.insert(1, '!');
|
||||||
Applicability::MaybeIncorrect,
|
err.span_suggestion_verbose(
|
||||||
);
|
attr.span,
|
||||||
} else {
|
fluent::passes::suggestion,
|
||||||
err.span_help(attr.span, fluent::passes::help);
|
src,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_help(attr.span, fluent::passes::help);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
err.note(fluent::passes::note);
|
||||||
err.note(fluent::passes::note).emit();
|
err
|
||||||
});
|
},
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::{pluralize, Applicability, MultiSpan};
|
use rustc_errors::{pluralize, Applicability, DelayDm, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
@ -184,13 +184,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
|||||||
lint::builtin::DEAD_CODE,
|
lint::builtin::DEAD_CODE,
|
||||||
assign.hir_id,
|
assign.hir_id,
|
||||||
assign.span,
|
assign.span,
|
||||||
|lint| {
|
DelayDm(|| format!(
|
||||||
lint.build(&format!(
|
|
||||||
"useless assignment of {} of type `{}` to itself",
|
"useless assignment of {} of type `{}` to itself",
|
||||||
if is_field_assign { "field" } else { "variable" },
|
if is_field_assign { "field" } else { "variable" },
|
||||||
self.typeck_results().expr_ty(lhs),
|
self.typeck_results().expr_ty(lhs),
|
||||||
))
|
)),
|
||||||
.emit();
|
|lint| {
|
||||||
|
lint
|
||||||
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -717,6 +718,26 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
||||||
|
let span_len = dead_codes.len();
|
||||||
|
let names = match &names[..] {
|
||||||
|
_ if span_len > 6 => String::new(),
|
||||||
|
[name] => format!("`{name}` "),
|
||||||
|
[names @ .., last] => {
|
||||||
|
format!(
|
||||||
|
"{} and `{last}` ",
|
||||||
|
names.iter().map(|name| format!("`{name}`")).join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
[] => unreachable!(),
|
||||||
|
};
|
||||||
|
let msg = format!(
|
||||||
|
"{these}{descr}{s} {names}{are} never {participle}",
|
||||||
|
these = if span_len > 6 { "multiple " } else { "" },
|
||||||
|
s = pluralize!(span_len),
|
||||||
|
are = pluralize!("is", span_len),
|
||||||
|
);
|
||||||
|
|
||||||
tcx.struct_span_lint_hir(
|
tcx.struct_span_lint_hir(
|
||||||
if is_positional {
|
if is_positional {
|
||||||
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
|
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
|
||||||
@ -725,27 +746,8 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||||||
},
|
},
|
||||||
tcx.hir().local_def_id_to_hir_id(first_id),
|
tcx.hir().local_def_id_to_hir_id(first_id),
|
||||||
MultiSpan::from_spans(spans.clone()),
|
MultiSpan::from_spans(spans.clone()),
|
||||||
|lint| {
|
msg,
|
||||||
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
|err| {
|
||||||
let span_len = dead_codes.len();
|
|
||||||
let names = match &names[..] {
|
|
||||||
_ if span_len > 6 => String::new(),
|
|
||||||
[name] => format!("`{name}` "),
|
|
||||||
[names @ .., last] => {
|
|
||||||
format!(
|
|
||||||
"{} and `{last}` ",
|
|
||||||
names.iter().map(|name| format!("`{name}`")).join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
[] => unreachable!(),
|
|
||||||
};
|
|
||||||
let mut err = lint.build(&format!(
|
|
||||||
"{these}{descr}{s} {names}{are} never {participle}",
|
|
||||||
these = if span_len > 6 { "multiple " } else { "" },
|
|
||||||
s = pluralize!(span_len),
|
|
||||||
are = pluralize!("is", span_len),
|
|
||||||
));
|
|
||||||
|
|
||||||
if is_positional {
|
if is_positional {
|
||||||
err.multipart_suggestion(
|
err.multipart_suggestion(
|
||||||
&format!(
|
&format!(
|
||||||
@ -791,7 +793,7 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||||||
);
|
);
|
||||||
err.note(&msg);
|
err.note(&msg);
|
||||||
}
|
}
|
||||||
err.emit();
|
err
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1319,14 +1319,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
// that we do not emit the same warning twice if the uninhabited type
|
// that we do not emit the same warning twice if the uninhabited type
|
||||||
// is indeed `!`.
|
// is indeed `!`.
|
||||||
|
|
||||||
|
let msg = format!("unreachable {}", descr);
|
||||||
self.ir.tcx.struct_span_lint_hir(
|
self.ir.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::UNREACHABLE_CODE,
|
lint::builtin::UNREACHABLE_CODE,
|
||||||
expr_id,
|
expr_id,
|
||||||
expr_span,
|
expr_span,
|
||||||
|lint| {
|
&msg,
|
||||||
let msg = format!("unreachable {}", descr);
|
|diag| {
|
||||||
lint.build(&msg)
|
diag.span_label(expr_span, &msg)
|
||||||
.span_label(expr_span, &msg)
|
|
||||||
.span_label(orig_span, "any code following this expression is unreachable")
|
.span_label(orig_span, "any code following this expression is unreachable")
|
||||||
.span_note(
|
.span_note(
|
||||||
orig_span,
|
orig_span,
|
||||||
@ -1335,7 +1335,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
orig_ty
|
orig_ty
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1491,14 +1490,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
lint::builtin::UNUSED_ASSIGNMENTS,
|
lint::builtin::UNUSED_ASSIGNMENTS,
|
||||||
var_hir_id,
|
var_hir_id,
|
||||||
vec![span],
|
vec![span],
|
||||||
|lint| {
|
format!("value captured by `{}` is never read", name),
|
||||||
lint.build(&format!(
|
|lint| lint.help("did you mean to capture by reference instead?"),
|
||||||
"value captured by `{}` is never read",
|
|
||||||
name
|
|
||||||
))
|
|
||||||
.help("did you mean to capture by reference instead?")
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1508,11 +1501,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
lint::builtin::UNUSED_VARIABLES,
|
lint::builtin::UNUSED_VARIABLES,
|
||||||
var_hir_id,
|
var_hir_id,
|
||||||
vec![span],
|
vec![span],
|
||||||
|lint| {
|
format!("unused variable: `{}`", name),
|
||||||
lint.build(&format!("unused variable: `{}`", name))
|
|lint| lint.help("did you mean to capture by reference instead?"),
|
||||||
.help("did you mean to capture by reference instead?")
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1601,20 +1591,17 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, _, ident_span)| ident_span)
|
.map(|(_, _, ident_span)| ident_span)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|lint| {
|
format!("variable `{}` is assigned to, but never used", name),
|
||||||
lint.build(&format!("variable `{}` is assigned to, but never used", name))
|
|lint| lint.note(&format!("consider using `_{}` instead", name)),
|
||||||
.note(&format!("consider using `_{}` instead", name))
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
} else if can_remove {
|
} else if can_remove {
|
||||||
self.ir.tcx.struct_span_lint_hir(
|
self.ir.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::UNUSED_VARIABLES,
|
lint::builtin::UNUSED_VARIABLES,
|
||||||
first_hir_id,
|
first_hir_id,
|
||||||
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
|
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
|
||||||
|
format!("unused variable: `{}`", name),
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
lint.multipart_suggestion(
|
||||||
err.multipart_suggestion(
|
|
||||||
"try removing the field",
|
"try removing the field",
|
||||||
hir_ids_and_spans
|
hir_ids_and_spans
|
||||||
.iter()
|
.iter()
|
||||||
@ -1629,8 +1616,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
)
|
||||||
err.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -1661,14 +1647,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(_, pat_span, _)| *pat_span)
|
.map(|(_, pat_span, _)| *pat_span)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
format!("unused variable: `{}`", name),
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
lint.multipart_suggestion(
|
||||||
err.multipart_suggestion(
|
|
||||||
"try ignoring the field",
|
"try ignoring the field",
|
||||||
shorthands,
|
shorthands,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
)
|
||||||
err.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -1684,17 +1669,16 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(_, _, ident_span)| *ident_span)
|
.map(|(_, _, ident_span)| *ident_span)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
format!("unused variable: `{}`", name),
|
||||||
|lint| {
|
|lint| {
|
||||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
if self.has_added_lit_match_name_span(&name, opt_body, lint) {
|
||||||
if self.has_added_lit_match_name_span(&name, opt_body, &mut err) {
|
lint.span_label(pat.span, "unused variable");
|
||||||
err.span_label(pat.span, "unused variable");
|
|
||||||
}
|
}
|
||||||
err.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
"if this is intentional, prefix it with an underscore",
|
"if this is intentional, prefix it with an underscore",
|
||||||
non_shorthands,
|
non_shorthands,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
)
|
||||||
err.emit();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1758,11 +1742,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
lint::builtin::UNUSED_ASSIGNMENTS,
|
lint::builtin::UNUSED_ASSIGNMENTS,
|
||||||
hir_id,
|
hir_id,
|
||||||
spans,
|
spans,
|
||||||
|lint| {
|
message(&name),
|
||||||
lint.build(&message(&name))
|
|lint| lint.help("maybe it is overwritten before being read?"),
|
||||||
.help("maybe it is overwritten before being read?")
|
|
||||||
.emit();
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,13 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
|
|||||||
if abi == Abi::Rust {
|
if abi == Abi::Rust {
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
let span = tcx.def_span(def_id);
|
let span = tcx.def_span(def_id);
|
||||||
tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
lint.build("Rust ABI is unsupported in naked functions").emit();
|
UNDEFINED_NAKED_FUNCTION_ABI,
|
||||||
});
|
hir_id,
|
||||||
|
span,
|
||||||
|
"Rust ABI is unsupported in naked functions",
|
||||||
|
|lint| lint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,10 +752,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||||||
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
||||||
item.hir_id(),
|
item.hir_id(),
|
||||||
span,
|
span,
|
||||||
|lint| {lint
|
"an `#[unstable]` annotation here has no effect",
|
||||||
.build("an `#[unstable]` annotation here has no effect")
|
|lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
||||||
.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
|
||||||
.emit();}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1081,11 +1079,16 @@ fn unnecessary_partially_stable_feature_lint(
|
|||||||
implies: Symbol,
|
implies: Symbol,
|
||||||
since: Symbol,
|
since: Symbol,
|
||||||
) {
|
) {
|
||||||
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
lint.build(&format!(
|
lint::builtin::STABLE_FEATURES,
|
||||||
|
hir::CRATE_HIR_ID,
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
|
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
|
||||||
by the feature `{implies}`"
|
by the feature `{implies}`"
|
||||||
))
|
),
|
||||||
|
|lint| {
|
||||||
|
lint
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
@ -1100,8 +1103,8 @@ fn unnecessary_partially_stable_feature_lint(
|
|||||||
"",
|
"",
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unnecessary_stable_feature_lint(
|
fn unnecessary_stable_feature_lint(
|
||||||
@ -1113,12 +1116,8 @@ fn unnecessary_stable_feature_lint(
|
|||||||
if since.as_str() == VERSION_PLACEHOLDER {
|
if since.as_str() == VERSION_PLACEHOLDER {
|
||||||
since = rust_version_symbol();
|
since = rust_version_symbol();
|
||||||
}
|
}
|
||||||
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
|
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| {
|
||||||
lint.build(&format!(
|
lint
|
||||||
"the feature `{feature}` has been stable since {since} and no longer requires an \
|
|
||||||
attribute to enable",
|
|
||||||
))
|
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,14 +235,18 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
|||||||
.emit()
|
.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
|
Err(ErrorHandled::TooGeneric) => {
|
||||||
NotConstEvaluatable::MentionsInfer
|
let err = if uv.has_infer_types_or_consts() {
|
||||||
|
NotConstEvaluatable::MentionsInfer
|
||||||
} else if uv.has_param_types_or_consts() {
|
} else if uv.has_param_types_or_consts() {
|
||||||
NotConstEvaluatable::MentionsParam
|
NotConstEvaluatable::MentionsParam
|
||||||
} else {
|
} else {
|
||||||
let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
|
let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
|
||||||
NotConstEvaluatable::Error(guar)
|
NotConstEvaluatable::Error(guar)
|
||||||
}),
|
};
|
||||||
|
|
||||||
|
Err(err)
|
||||||
|
},
|
||||||
Err(ErrorHandled::Linted) => {
|
Err(ErrorHandled::Linted) => {
|
||||||
let reported =
|
let reported =
|
||||||
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
|
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
|
||||||
@ -250,23 +254,23 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
|||||||
}
|
}
|
||||||
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
|
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if uv.substs.has_param_types_or_consts() {
|
if uv.substs.has_param_types_or_consts() {
|
||||||
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
|
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
|
||||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
|
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
|
||||||
|
|
||||||
if mir_body.is_polymorphic {
|
if mir_body.is_polymorphic {
|
||||||
let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
|
let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
|
||||||
tcx.struct_span_lint_hir(
|
tcx.struct_span_lint_hir(
|
||||||
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
||||||
tcx.hir().local_def_id_to_hir_id(local_def_id),
|
tcx.hir().local_def_id_to_hir_id(local_def_id),
|
||||||
span,
|
span,
|
||||||
|err| {
|
"cannot use constants which depend on generic parameters in types",
|
||||||
err.build("cannot use constants which depend on generic parameters in types").emit();
|
|err| err
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use crate::infer::TyCtxtInferExt;
|
|||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use crate::traits::{self, Obligation, ObligationCause};
|
use crate::traits::{self, Obligation, ObligationCause};
|
||||||
use hir::def::DefKind;
|
use hir::def::DefKind;
|
||||||
use rustc_errors::{FatalError, MultiSpan};
|
use rustc_errors::{DelayDm, FatalError, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst};
|
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst};
|
||||||
@ -164,37 +164,42 @@ fn lint_object_unsafe_trait(
|
|||||||
) {
|
) {
|
||||||
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
|
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
|
||||||
// It's also hard to get a use site span, so we use the method definition span.
|
// It's also hard to get a use site span, so we use the method definition span.
|
||||||
tcx.struct_span_lint_hir(WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, span, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
let mut err = lint.build(&format!(
|
WHERE_CLAUSES_OBJECT_SAFETY,
|
||||||
"the trait `{}` cannot be made into an object",
|
hir::CRATE_HIR_ID,
|
||||||
tcx.def_path_str(trait_def_id)
|
span,
|
||||||
));
|
DelayDm(|| format!("the trait `{}` cannot be made into an object", tcx.def_path_str(trait_def_id))),
|
||||||
let node = tcx.hir().get_if_local(trait_def_id);
|
|err| {
|
||||||
let mut spans = MultiSpan::from_span(span);
|
let node = tcx.hir().get_if_local(trait_def_id);
|
||||||
if let Some(hir::Node::Item(item)) = node {
|
let mut spans = MultiSpan::from_span(span);
|
||||||
spans.push_span_label(item.ident.span, "this trait cannot be made into an object...");
|
if let Some(hir::Node::Item(item)) = node {
|
||||||
spans.push_span_label(span, format!("...because {}", violation.error_msg()));
|
spans.push_span_label(
|
||||||
} else {
|
item.ident.span,
|
||||||
spans.push_span_label(
|
"this trait cannot be made into an object...",
|
||||||
span,
|
);
|
||||||
format!(
|
spans.push_span_label(span, format!("...because {}", violation.error_msg()));
|
||||||
"the trait cannot be made into an object because {}",
|
} else {
|
||||||
violation.error_msg()
|
spans.push_span_label(
|
||||||
),
|
span,
|
||||||
|
format!(
|
||||||
|
"the trait cannot be made into an object because {}",
|
||||||
|
violation.error_msg()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
err.span_note(
|
||||||
|
spans,
|
||||||
|
"for a trait to be \"object safe\" it needs to allow building a vtable to allow the \
|
||||||
|
call to be resolvable dynamically; for more information visit \
|
||||||
|
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
||||||
);
|
);
|
||||||
};
|
if node.is_some() {
|
||||||
err.span_note(
|
// Only provide the help if its a local trait, otherwise it's not
|
||||||
spans,
|
violation.solution(err);
|
||||||
"for a trait to be \"object safe\" it needs to allow building a vtable to allow the \
|
}
|
||||||
call to be resolvable dynamically; for more information visit \
|
err
|
||||||
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
|
},
|
||||||
);
|
);
|
||||||
if node.is_some() {
|
|
||||||
// Only provide the help if its a local trait, otherwise it's not
|
|
||||||
violation.solution(&mut err);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sized_trait_bound_spans<'tcx>(
|
fn sized_trait_bound_spans<'tcx>(
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
|
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
|
||||||
use hir::LangItem;
|
use hir::LangItem;
|
||||||
|
use rustc_errors::DelayDm;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
@ -825,13 +826,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
DEREF_INTO_DYN_SUPERTRAIT,
|
DEREF_INTO_DYN_SUPERTRAIT,
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
|lint| {
|
DelayDm(|| format!(
|
||||||
lint.build(&format!(
|
"`{}` implements `Deref` with supertrait `{}` as output",
|
||||||
"`{}` implements `Deref` with supertrait `{}` as output",
|
source, deref_output_ty
|
||||||
source,
|
)),
|
||||||
deref_output_ty
|
|lint| lint,
|
||||||
)).emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
|||||||
use crate::traits::select::IntercrateAmbiguityCause;
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
|
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder};
|
use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::ty::{self, ImplSubject, TyCtxt};
|
use rustc_middle::ty::{self, ImplSubject, TyCtxt};
|
||||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||||
@ -350,26 +350,12 @@ fn report_conflicting_impls(
|
|||||||
// Work to be done after we've built the DiagnosticBuilder. We have to define it
|
// Work to be done after we've built the DiagnosticBuilder. We have to define it
|
||||||
// now because the struct_lint methods don't return back the DiagnosticBuilder
|
// now because the struct_lint methods don't return back the DiagnosticBuilder
|
||||||
// that's passed in.
|
// that's passed in.
|
||||||
fn decorate<G: EmissionGuarantee>(
|
fn decorate<'a, 'b, G: EmissionGuarantee>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
overlap: OverlapError,
|
overlap: OverlapError,
|
||||||
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
|
|
||||||
impl_span: Span,
|
impl_span: Span,
|
||||||
err: LintDiagnosticBuilder<'_, G>,
|
err: &'b mut DiagnosticBuilder<'a, G>,
|
||||||
) -> G {
|
) -> &'b mut DiagnosticBuilder<'a, G> {
|
||||||
let msg = format!(
|
|
||||||
"conflicting implementations of trait `{}`{}{}",
|
|
||||||
overlap.trait_desc,
|
|
||||||
overlap
|
|
||||||
.self_desc
|
|
||||||
.clone()
|
|
||||||
.map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }),
|
|
||||||
match used_to_be_allowed {
|
|
||||||
Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)",
|
|
||||||
_ => "",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let mut err = err.build(&msg);
|
|
||||||
match tcx.span_of_impl(overlap.with_impl) {
|
match tcx.span_of_impl(overlap.with_impl) {
|
||||||
Ok(span) => {
|
Ok(span) => {
|
||||||
err.span_label(span, "first implementation here");
|
err.span_label(span, "first implementation here");
|
||||||
@ -384,7 +370,9 @@ fn report_conflicting_impls(
|
|||||||
}
|
}
|
||||||
Err(cname) => {
|
Err(cname) => {
|
||||||
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
|
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
|
||||||
Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s),
|
Some(s) => {
|
||||||
|
format!("conflicting implementation in crate `{}`:\n- {}", cname, s)
|
||||||
|
}
|
||||||
None => format!("conflicting implementation in crate `{}`", cname),
|
None => format!("conflicting implementation in crate `{}`", cname),
|
||||||
};
|
};
|
||||||
err.note(&msg);
|
err.note(&msg);
|
||||||
@ -392,28 +380,33 @@ fn report_conflicting_impls(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for cause in &overlap.intercrate_ambiguity_causes {
|
for cause in &overlap.intercrate_ambiguity_causes {
|
||||||
cause.add_intercrate_ambiguity_hint(&mut err);
|
cause.add_intercrate_ambiguity_hint(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if overlap.involves_placeholder {
|
if overlap.involves_placeholder {
|
||||||
coherence::add_placeholder_note(&mut err);
|
coherence::add_placeholder_note(err);
|
||||||
}
|
}
|
||||||
err.emit()
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let msg = format!(
|
||||||
|
"conflicting implementations of trait `{}`{}{}",
|
||||||
|
overlap.trait_desc,
|
||||||
|
overlap.self_desc.as_deref().map_or_else(String::new, |ty| format!(" for type `{ty}`")),
|
||||||
|
match used_to_be_allowed {
|
||||||
|
Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)",
|
||||||
|
_ => "",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
match used_to_be_allowed {
|
match used_to_be_allowed {
|
||||||
None => {
|
None => {
|
||||||
let reported = if overlap.with_impl.is_local()
|
let reported = if overlap.with_impl.is_local()
|
||||||
|| tcx.orphan_check_impl(impl_def_id).is_ok()
|
|| tcx.orphan_check_impl(impl_def_id).is_ok()
|
||||||
{
|
{
|
||||||
let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
|
let mut err = struct_span_err!(tcx.sess, impl_span, E0119, "{msg}",);
|
||||||
Some(decorate(
|
decorate(tcx, overlap, impl_span, &mut err);
|
||||||
tcx,
|
Some(err.emit())
|
||||||
overlap,
|
|
||||||
used_to_be_allowed,
|
|
||||||
impl_span,
|
|
||||||
LintDiagnosticBuilder::new(err),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
|
Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
|
||||||
};
|
};
|
||||||
@ -428,9 +421,8 @@ fn report_conflicting_impls(
|
|||||||
lint,
|
lint,
|
||||||
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
tcx.hir().local_def_id_to_hir_id(impl_def_id),
|
||||||
impl_span,
|
impl_span,
|
||||||
|ldb| {
|
msg,
|
||||||
decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
|
|err| decorate(tcx, overlap, impl_span, err),
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -404,12 +404,8 @@ pub(crate) fn run_global_ctxt(
|
|||||||
tcx.struct_lint_node(
|
tcx.struct_lint_node(
|
||||||
crate::lint::MISSING_CRATE_LEVEL_DOCS,
|
crate::lint::MISSING_CRATE_LEVEL_DOCS,
|
||||||
DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
|
DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
|
||||||
|lint| {
|
"no documentation found for this crate's top-level module",
|
||||||
let mut diag =
|
|lint| lint.help(help),
|
||||||
lint.build("no documentation found for this crate's top-level module");
|
|
||||||
diag.help(&help);
|
|
||||||
diag.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,11 +813,8 @@ impl<'tcx> ExtraInfo<'tcx> {
|
|||||||
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
|
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
|
||||||
hir_id,
|
hir_id,
|
||||||
self.sp,
|
self.sp,
|
||||||
|lint| {
|
msg,
|
||||||
let mut diag = lint.build(msg);
|
|lint| lint.help(help),
|
||||||
diag.help(help);
|
|
||||||
diag.emit();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,16 +71,14 @@ impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
|
|||||||
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
|
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
|
||||||
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
|
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
|
||||||
.unwrap_or_else(|| item.attr_span(cx.tcx));
|
.unwrap_or_else(|| item.attr_span(cx.tcx));
|
||||||
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| {
|
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
|
||||||
lint.build(msg)
|
lint.note("bare URLs are not automatically turned into clickable links")
|
||||||
.note("bare URLs are not automatically turned into clickable links")
|
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
sp,
|
sp,
|
||||||
"use an automatic link instead",
|
"use an automatic link instead",
|
||||||
format!("<{}>", url),
|
format!("<{}>", url),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
use rustc_data_structures::sync::{Lock, Lrc};
|
use rustc_data_structures::sync::{Lock, Lrc};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
|
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
|
||||||
LazyFallbackBundle, LintDiagnosticBuilder,
|
LazyFallbackBundle,
|
||||||
};
|
};
|
||||||
use rustc_parse::parse_stream_from_source_str;
|
use rustc_parse::parse_stream_from_source_str;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
@ -97,48 +97,10 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
|
|||||||
None => (item.attr_span(self.cx.tcx), false),
|
None => (item.attr_span(self.cx.tcx), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
// lambda that will use the lint to start a new diagnostic and add
|
let msg = if buffer.has_errors {
|
||||||
// a suggestion to it when needed.
|
"could not parse code block as Rust code"
|
||||||
let diag_builder = |lint: LintDiagnosticBuilder<'_, ()>| {
|
} else {
|
||||||
let explanation = if is_ignore {
|
"Rust code block is empty"
|
||||||
"`ignore` code blocks require valid Rust code for syntax highlighting; \
|
|
||||||
mark blocks that do not contain Rust code as text"
|
|
||||||
} else {
|
|
||||||
"mark blocks that do not contain Rust code as text"
|
|
||||||
};
|
|
||||||
let msg = if buffer.has_errors {
|
|
||||||
"could not parse code block as Rust code"
|
|
||||||
} else {
|
|
||||||
"Rust code block is empty"
|
|
||||||
};
|
|
||||||
let mut diag = lint.build(msg);
|
|
||||||
|
|
||||||
if precise_span {
|
|
||||||
if is_ignore {
|
|
||||||
// giving an accurate suggestion is hard because `ignore` might not have come first in the list.
|
|
||||||
// just give a `help` instead.
|
|
||||||
diag.span_help(
|
|
||||||
sp.from_inner(InnerSpan::new(0, 3)),
|
|
||||||
&format!("{}: ```text", explanation),
|
|
||||||
);
|
|
||||||
} else if empty_block {
|
|
||||||
diag.span_suggestion(
|
|
||||||
sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
|
|
||||||
explanation,
|
|
||||||
"text",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if empty_block || is_ignore {
|
|
||||||
diag.help(&format!("{}: ```text", explanation));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(#67563): Provide more context for these errors by displaying the spans inline.
|
|
||||||
for message in buffer.messages.iter() {
|
|
||||||
diag.note(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
diag.emit();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Finally build and emit the completed diagnostic.
|
// Finally build and emit the completed diagnostic.
|
||||||
@ -148,7 +110,42 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
|
|||||||
crate::lint::INVALID_RUST_CODEBLOCKS,
|
crate::lint::INVALID_RUST_CODEBLOCKS,
|
||||||
hir_id,
|
hir_id,
|
||||||
sp,
|
sp,
|
||||||
diag_builder,
|
msg,
|
||||||
|
|lint| {
|
||||||
|
let explanation = if is_ignore {
|
||||||
|
"`ignore` code blocks require valid Rust code for syntax highlighting; \
|
||||||
|
mark blocks that do not contain Rust code as text"
|
||||||
|
} else {
|
||||||
|
"mark blocks that do not contain Rust code as text"
|
||||||
|
};
|
||||||
|
|
||||||
|
if precise_span {
|
||||||
|
if is_ignore {
|
||||||
|
// giving an accurate suggestion is hard because `ignore` might not have come first in the list.
|
||||||
|
// just give a `help` instead.
|
||||||
|
lint.span_help(
|
||||||
|
sp.from_inner(InnerSpan::new(0, 3)),
|
||||||
|
&format!("{}: ```text", explanation),
|
||||||
|
);
|
||||||
|
} else if empty_block {
|
||||||
|
lint.span_suggestion(
|
||||||
|
sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
|
||||||
|
explanation,
|
||||||
|
"text",
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if empty_block || is_ignore {
|
||||||
|
lint.help(&format!("{}: ```text", explanation));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(#67563): Provide more context for these errors by displaying the spans inline.
|
||||||
|
for message in buffer.messages.iter() {
|
||||||
|
lint.note(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
lint
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,9 +125,8 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
|
|||||||
crate::lint::MISSING_DOC_CODE_EXAMPLES,
|
crate::lint::MISSING_DOC_CODE_EXAMPLES,
|
||||||
hir_id,
|
hir_id,
|
||||||
sp,
|
sp,
|
||||||
|lint| {
|
"missing code example in this documentation",
|
||||||
lint.build("missing code example in this documentation").emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if tests.found_tests > 0
|
} else if tests.found_tests > 0
|
||||||
@ -137,9 +136,8 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
|
|||||||
crate::lint::PRIVATE_DOC_TESTS,
|
crate::lint::PRIVATE_DOC_TESTS,
|
||||||
hir_id,
|
hir_id,
|
||||||
item.attr_span(cx.tcx),
|
item.attr_span(cx.tcx),
|
||||||
|lint| {
|
"documentation test in private item",
|
||||||
lint.build("documentation test in private item").emit();
|
|lint| lint,
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1609,9 +1609,7 @@ fn report_diagnostic(
|
|||||||
|
|
||||||
let sp = item.attr_span(tcx);
|
let sp = item.attr_span(tcx);
|
||||||
|
|
||||||
tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
|
tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| {
|
||||||
let mut diag = lint.build(msg);
|
|
||||||
|
|
||||||
let span =
|
let span =
|
||||||
super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
|
super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
|
||||||
if dox.as_bytes().get(link_range.start) == Some(&b'`')
|
if dox.as_bytes().get(link_range.start) == Some(&b'`')
|
||||||
@ -1624,7 +1622,7 @@ fn report_diagnostic(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(sp) = span {
|
if let Some(sp) = span {
|
||||||
diag.set_span(sp);
|
lint.set_span(sp);
|
||||||
} else {
|
} else {
|
||||||
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
|
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
|
||||||
// ^ ~~~~
|
// ^ ~~~~
|
||||||
@ -1634,7 +1632,7 @@ fn report_diagnostic(
|
|||||||
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
|
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
|
||||||
|
|
||||||
// Print the line containing the `link_range` and manually mark it with '^'s.
|
// Print the line containing the `link_range` and manually mark it with '^'s.
|
||||||
diag.note(&format!(
|
lint.note(&format!(
|
||||||
"the link appears in this line:\n\n{line}\n\
|
"the link appears in this line:\n\n{line}\n\
|
||||||
{indicator: <before$}{indicator:^<found$}",
|
{indicator: <before$}{indicator:^<found$}",
|
||||||
line = line,
|
line = line,
|
||||||
@ -1644,9 +1642,9 @@ fn report_diagnostic(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
decorate(&mut diag, span);
|
decorate(lint, span);
|
||||||
|
|
||||||
diag.emit();
|
lint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,9 +240,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
|
|||||||
Some(sp) => sp,
|
Some(sp) => sp,
|
||||||
None => item.attr_span(tcx),
|
None => item.attr_span(tcx),
|
||||||
};
|
};
|
||||||
tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
|
tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
|
||||||
use rustc_lint_defs::Applicability;
|
use rustc_lint_defs::Applicability;
|
||||||
let mut diag = lint.build(msg);
|
|
||||||
// If a tag looks like `<this>`, it might actually be a generic.
|
// If a tag looks like `<this>`, it might actually be a generic.
|
||||||
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
|
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
|
||||||
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
|
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
|
||||||
@ -305,11 +304,10 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
|
|||||||
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|
||||||
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
|
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
|
||||||
{
|
{
|
||||||
diag.emit();
|
return lint;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
|
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
|
||||||
diag.multipart_suggestion(
|
lint.multipart_suggestion(
|
||||||
"try marking as source code",
|
"try marking as source code",
|
||||||
vec![
|
vec![
|
||||||
(generics_sp.shrink_to_lo(), String::from("`")),
|
(generics_sp.shrink_to_lo(), String::from("`")),
|
||||||
@ -318,7 +316,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
|
|||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
diag.emit()
|
|
||||||
|
lint
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ error: this URL is not a hyperlink
|
|||||||
LL | /// https://somewhere.com
|
LL | /// https://somewhere.com
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com>`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com>`
|
||||||
|
|
|
|
||||||
|
= note: bare URLs are not automatically turned into clickable links
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/bare-urls.rs:3:9
|
--> $DIR/bare-urls.rs:3:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::bare_urls)]
|
LL | #![deny(rustdoc::bare_urls)]
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
= note: bare URLs are not automatically turned into clickable links
|
|
||||||
|
|
||||||
error: this URL is not a hyperlink
|
error: this URL is not a hyperlink
|
||||||
--> $DIR/bare-urls.rs:7:5
|
--> $DIR/bare-urls.rs:7:5
|
||||||
|
@ -8,12 +8,12 @@ error: unknown attribute `compile-fail`. Did you mean `compile_fail`?
|
|||||||
9 | | /// ```
|
9 | | /// ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
|
= help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/check-attr-test.rs:3:9
|
--> $DIR/check-attr-test.rs:3:9
|
||||||
|
|
|
|
||||||
3 | #![deny(rustdoc::invalid_codeblock_attributes)]
|
3 | #![deny(rustdoc::invalid_codeblock_attributes)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
|
|
||||||
|
|
||||||
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
|
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
|
||||||
--> $DIR/check-attr-test.rs:5:1
|
--> $DIR/check-attr-test.rs:5:1
|
||||||
|
@ -10,12 +10,12 @@ LL | | /// boo
|
|||||||
LL | | /// ```
|
LL | | /// ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
|
= help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/check-attr.rs:1:9
|
--> $DIR/check-attr.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::invalid_codeblock_attributes)]
|
LL | #![deny(rustdoc::invalid_codeblock_attributes)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
|
|
||||||
|
|
||||||
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
|
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
|
||||||
--> $DIR/check-attr.rs:3:1
|
--> $DIR/check-attr.rs:3:1
|
||||||
|
@ -4,8 +4,8 @@ warning: unexpected `cfg` condition value
|
|||||||
LL | #[cfg(feature = "invalid")]
|
LL | #[cfg(feature = "invalid")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
|
||||||
= note: expected values for `feature` are: test
|
= note: expected values for `feature` are: test
|
||||||
|
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ LL | | //! let x = 12;
|
|||||||
LL | | //! ```
|
LL | | //! ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
= note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
|
|
||||||
= help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
|
= help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
|
||||||
|
= note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
|
||||||
|
|
||||||
error: unknown attribute `testharness`. Did you mean `test_harness`?
|
error: unknown attribute `testharness`. Did you mean `test_harness`?
|
||||||
--> $DIR/check-fail.rs:16:1
|
--> $DIR/check-fail.rs:16:1
|
||||||
|
@ -24,14 +24,14 @@ LL | pub fn foo() {}
|
|||||||
|
|
||||||
warning: no documentation found for this crate's top-level module
|
warning: no documentation found for this crate's top-level module
|
||||||
|
|
|
|
||||||
|
= help: The following guide may be of use:
|
||||||
|
https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/check.rs:10:9
|
--> $DIR/check.rs:10:9
|
||||||
|
|
|
|
||||||
LL | #![warn(rustdoc::all)]
|
LL | #![warn(rustdoc::all)]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
= note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
|
= note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
|
||||||
= help: The following guide may be of use:
|
|
||||||
https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
|
|
||||||
|
|
||||||
warning: missing code example in this documentation
|
warning: missing code example in this documentation
|
||||||
--> $DIR/check.rs:5:1
|
--> $DIR/check.rs:5:1
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `v2`
|
|||||||
LL | /// [v2]
|
LL | /// [v2]
|
||||||
| ^^ no item named `v2` in scope
|
| ^^ no item named `v2` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/deny-intra-link-resolution-failure.rs:1:9
|
--> $DIR/deny-intra-link-resolution-failure.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ error: this URL is not a hyperlink
|
|||||||
LL | ... a http://link.com
|
LL | ... a http://link.com
|
||||||
| ^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://link.com>`
|
| ^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://link.com>`
|
||||||
|
|
|
|
||||||
|
= note: bare URLs are not automatically turned into clickable links
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/diagnostic-width.rs:2:9
|
--> $DIR/diagnostic-width.rs:2:9
|
||||||
|
|
|
|
||||||
LL | ...ny(rustdoc::bare_url...
|
LL | ...ny(rustdoc::bare_url...
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
= note: bare URLs are not automatically turned into clickable links
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,14 +4,14 @@ error: unknown `doc` attribute `as_ptr`
|
|||||||
LL | #[doc(as_ptr)]
|
LL | #[doc(as_ptr)]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/doc-attr.rs:2:9
|
--> $DIR/doc-attr.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(warnings)]
|
LL | #![deny(warnings)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
|
|
||||||
error: invalid `doc` attribute
|
error: invalid `doc` attribute
|
||||||
--> $DIR/doc-attr.rs:12:7
|
--> $DIR/doc-attr.rs:12:7
|
||||||
|
@ -4,9 +4,9 @@ warning: unknown `doc` attribute `include`
|
|||||||
LL | #[doc(include = "external-cross-doc.md")]
|
LL | #[doc(include = "external-cross-doc.md")]
|
||||||
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
|
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
|
||||||
|
|
|
|
||||||
= note: `#[warn(invalid_doc_attributes)]` on by default
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: `#[warn(invalid_doc_attributes)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
@ -4,16 +4,16 @@ error: unknown `doc` attribute `spotlight`
|
|||||||
LL | #[doc(spotlight)]
|
LL | #[doc(spotlight)]
|
||||||
| ^^^^^^^^^ help: use `notable_trait` instead
|
| ^^^^^^^^^ help: use `notable_trait` instead
|
||||||
|
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: `doc(spotlight)` was renamed to `doc(notable_trait)`
|
||||||
|
= note: `doc(spotlight)` is now a no-op
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/doc-spotlight.rs:2:9
|
--> $DIR/doc-spotlight.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(warnings)]
|
LL | #![deny(warnings)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: `doc(spotlight)` was renamed to `doc(notable_trait)`
|
|
||||||
= note: `doc(spotlight)` is now a no-op
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@ error: `#[doc(test(...)]` takes a list of attributes
|
|||||||
LL | #![doc(test)]
|
LL | #![doc(test)]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/doc-test-attr.rs:2:9
|
--> $DIR/doc-test-attr.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(invalid_doc_attributes)]
|
LL | #![deny(invalid_doc_attributes)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
|
|
||||||
error: `#[doc(test(...)]` takes a list of attributes
|
error: `#[doc(test(...)]` takes a list of attributes
|
||||||
--> $DIR/doc-test-attr.rs:7:8
|
--> $DIR/doc-test-attr.rs:7:8
|
||||||
|
@ -7,12 +7,12 @@ LL | | //! foo'b'
|
|||||||
LL | | //! ```
|
LL | | //! ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
|
= note: error from rustc: prefix `foo` is unknown
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/doctest-edition.rs:3:9
|
--> $DIR/doctest-edition.rs:3:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::invalid_rust_codeblocks)]
|
LL | #![deny(rustdoc::invalid_rust_codeblocks)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: error from rustc: prefix `foo` is unknown
|
|
||||||
help: mark blocks that do not contain Rust code as text
|
help: mark blocks that do not contain Rust code as text
|
||||||
|
|
|
|
||||||
LL | //! ```text
|
LL | //! ```text
|
||||||
|
@ -4,14 +4,14 @@ error: unknown lint: `rustdoc::missing_doc_code_examples`
|
|||||||
LL | #![allow(rustdoc::missing_doc_code_examples)]
|
LL | #![allow(rustdoc::missing_doc_code_examples)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
= note: the `rustdoc::missing_doc_code_examples` lint is unstable
|
||||||
|
= note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
|
||||||
|
= help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9
|
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(unknown_lints)]
|
LL | #![deny(unknown_lints)]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: the `rustdoc::missing_doc_code_examples` lint is unstable
|
|
||||||
= note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
|
|
||||||
= help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: unknown lint: `rustdoc::missing_doc_code_examples`
|
error: unknown lint: `rustdoc::missing_doc_code_examples`
|
||||||
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
|
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
|
||||||
|
@ -7,13 +7,13 @@ LL | | /// let heart = '❤️';
|
|||||||
LL | | /// ```
|
LL | | /// ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
= note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
|
|
||||||
help: `ignore` code blocks require valid Rust code for syntax highlighting; mark blocks that do not contain Rust code as text: ```text
|
help: `ignore` code blocks require valid Rust code for syntax highlighting; mark blocks that do not contain Rust code as text: ```text
|
||||||
--> $DIR/ignore-block-help.rs:3:5
|
--> $DIR/ignore-block-help.rs:3:5
|
||||||
|
|
|
|
||||||
LL | /// ```ignore (to-prevent-tidy-error)
|
LL | /// ```ignore (to-prevent-tidy-error)
|
||||||
| ^^^
|
| ^^^
|
||||||
= note: error from rustc: character literal may only contain one codepoint
|
= note: error from rustc: character literal may only contain one codepoint
|
||||||
|
= note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `NonExistentStruct`
|
|||||||
LL | /// This [test][NonExistentStruct<i32>] thing!
|
LL | /// This [test][NonExistentStruct<i32>] thing!
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope
|
| ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/html-as-generics-intra-doc.rs:2:9
|
--> $DIR/html-as-generics-intra-doc.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
error: unresolved link to `NonExistentStruct2`
|
error: unresolved link to `NonExistentStruct2`
|
||||||
--> $DIR/html-as-generics-intra-doc.rs:17:11
|
--> $DIR/html-as-generics-intra-doc.rs:17:11
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `before_but_limited_to_module`
|
|||||||
LL | /// [before_but_limited_to_module]
|
LL | /// [before_but_limited_to_module]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `before_but_limited_to_module` in scope
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `before_but_limited_to_module` in scope
|
||||||
|
|
|
|
||||||
|
= note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/macro-rules-error.rs:5:9
|
--> $DIR/macro-rules-error.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
|
|
||||||
|
|
||||||
error: unresolved link to `after`
|
error: unresolved link to `after`
|
||||||
--> $DIR/macro-rules-error.rs:15:6
|
--> $DIR/macro-rules-error.rs:15:6
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `T`
|
|||||||
LL | //! [[T]::rotate_left]
|
LL | //! [[T]::rotate_left]
|
||||||
| ^ no item named `T` in scope
|
| ^ no item named `T` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/non-path-primitives.rs:1:9
|
--> $DIR/non-path-primitives.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
error: unresolved link to `Z`
|
error: unresolved link to `Z`
|
||||||
--> $DIR/non-path-primitives.rs:14:5
|
--> $DIR/non-path-primitives.rs:14:5
|
||||||
|
@ -4,8 +4,8 @@ warning: public documentation for `private_from_crate_level` links to private it
|
|||||||
LL | //! [my_module]
|
LL | //! [my_module]
|
||||||
| ^^^^^^^^^ this item is private
|
| ^^^^^^^^^ this item is private
|
||||||
|
|
|
|
||||||
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
|
||||||
= note: this link will resolve properly if you pass `--document-private-items`
|
= note: this link will resolve properly if you pass `--document-private-items`
|
||||||
|
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
|
|||||||
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
|
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
|
||||||
| ^^^^^^^^^ this item is private
|
| ^^^^^^^^^ this item is private
|
||||||
|
|
|
|
||||||
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
|
||||||
= note: this link resolves only because you passed `--document-private-items`, but will break without
|
= note: this link resolves only because you passed `--document-private-items`, but will break without
|
||||||
|
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
||||||
|
|
||||||
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
|
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
|
||||||
--> $DIR/private.rs:7:23
|
--> $DIR/private.rs:7:23
|
||||||
|
@ -4,8 +4,8 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
|
|||||||
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
|
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
|
||||||
| ^^^^^^^^^ this item is private
|
| ^^^^^^^^^ this item is private
|
||||||
|
|
|
|
||||||
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
|
||||||
= note: this link will resolve properly if you pass `--document-private-items`
|
= note: this link will resolve properly if you pass `--document-private-items`
|
||||||
|
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
|
||||||
|
|
||||||
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
|
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
|
||||||
--> $DIR/private.rs:7:23
|
--> $DIR/private.rs:7:23
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `i`
|
|||||||
LL | /// (arr[i])
|
LL | /// (arr[i])
|
||||||
| ^ no item named `i` in scope
|
| ^ no item named `i` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/span-ice-55723.rs:1:9
|
--> $DIR/span-ice-55723.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ warning: unresolved link to `Oooops`
|
|||||||
LL | /// [Oooops]
|
LL | /// [Oooops]
|
||||||
| ^^^^^^ no item named `Oooops` in scope
|
| ^^^^^^ no item named `Oooops` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/through-proc-macro.rs:7:9
|
--> $DIR/through-proc-macro.rs:7:9
|
||||||
|
|
|
|
||||||
LL | #![warn(rustdoc::broken_intra_doc_links)]
|
LL | #![warn(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@ error: unknown disambiguator `foo`
|
|||||||
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
|
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/unknown-disambiguator.rs:2:9
|
--> $DIR/unknown-disambiguator.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(warnings)]
|
LL | #![deny(warnings)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
|
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
|
||||||
= note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
|
|
||||||
|
|
||||||
error: unknown disambiguator `bar`
|
error: unknown disambiguator `bar`
|
||||||
--> $DIR/unknown-disambiguator.rs:4:35
|
--> $DIR/unknown-disambiguator.rs:4:35
|
||||||
|
@ -4,12 +4,12 @@ error: unresolved link to `zip`
|
|||||||
LL | /// See [zip] crate.
|
LL | /// See [zip] crate.
|
||||||
| ^^^ no item named `zip` in scope
|
| ^^^ no item named `zip` in scope
|
||||||
|
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/unused-extern-crate.rs:2:9
|
--> $DIR/unused-extern-crate.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ warning: unresolved link to `error`
|
|||||||
LL | /// [error]
|
LL | /// [error]
|
||||||
| ^^^^^ no item named `error` in scope
|
| ^^^^^ no item named `error` in scope
|
||||||
|
|
|
|
||||||
= note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
|
|
||||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
= note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
|
||||||
|
|
||||||
warning: unresolved link to `error1`
|
warning: unresolved link to `error1`
|
||||||
--> $DIR/warning-crlf.rs:12:11
|
--> $DIR/warning-crlf.rs:12:11
|
||||||
|
@ -4,15 +4,15 @@ error: this attribute can only be applied at the crate level
|
|||||||
LL | #[doc(test(no_crate_inject))]
|
LL | #[doc(test(no_crate_inject))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/invalid-doc-attr.rs:2:9
|
--> $DIR/invalid-doc-attr.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(warnings)]
|
LL | #![deny(warnings)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
|
||||||
help: to apply to the crate, use an inner attribute
|
help: to apply to the crate, use an inner attribute
|
||||||
|
|
|
|
||||||
LL | #![doc(test(no_crate_inject))]
|
LL | #![doc(test(no_crate_inject))]
|
||||||
|
@ -7,10 +7,10 @@ LL | | /// \__________pkt->size___________/ \_result->size_/ \__pkt->si
|
|||||||
LL | | /// ```
|
LL | | /// ```
|
||||||
| |_______^
|
| |_______^
|
||||||
|
|
|
|
||||||
|
= note: error from rustc: unknown start of token: \
|
||||||
|
= note: error from rustc: unknown start of token: \
|
||||||
|
= note: error from rustc: unknown start of token: \
|
||||||
= note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
|
= note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
|
||||||
= note: error from rustc: unknown start of token: \
|
|
||||||
= note: error from rustc: unknown start of token: \
|
|
||||||
= note: error from rustc: unknown start of token: \
|
|
||||||
help: mark blocks that do not contain Rust code as text
|
help: mark blocks that do not contain Rust code as text
|
||||||
|
|
|
|
||||||
LL | /// ```text
|
LL | /// ```text
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user