mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Improve non_fmt_panics suggestion based on trait impls.
This commit is contained in:
parent
23461b210f
commit
0a313250a4
@ -3932,6 +3932,7 @@ dependencies = [
|
|||||||
"rustc_feature",
|
"rustc_feature",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
|
"rustc_infer",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_parse_format",
|
"rustc_parse_format",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
|
@ -21,3 +21,4 @@ rustc_session = { path = "../rustc_session" }
|
|||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||||
|
rustc_infer = { path = "../rustc_infer" }
|
||||||
|
@ -2,12 +2,15 @@ use crate::{LateContext, LateLintPass, LintContext};
|
|||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_errors::{pluralize, Applicability};
|
use rustc_errors::{pluralize, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_parse_format::{ParseMode, Parser, Piece};
|
use rustc_parse_format::{ParseMode, Parser, Piece};
|
||||||
use rustc_session::lint::FutureIncompatibilityReason;
|
use rustc_session::lint::FutureIncompatibilityReason;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol};
|
use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol};
|
||||||
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first
|
/// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first
|
||||||
@ -129,20 +132,57 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
ty.ty_adt_def(),
|
ty.ty_adt_def(),
|
||||||
Some(ty_def) if cx.tcx.is_diagnostic_item(sym::string_type, ty_def.did),
|
Some(ty_def) if cx.tcx.is_diagnostic_item(sym::string_type, ty_def.did),
|
||||||
);
|
);
|
||||||
l.span_suggestion_verbose(
|
|
||||||
arg_span.shrink_to_lo(),
|
let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| {
|
||||||
"add a \"{}\" format string to Display the message",
|
let display = is_str || cx.tcx.get_diagnostic_item(sym::display_trait).map(|t| {
|
||||||
"\"{}\", ".into(),
|
infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply()
|
||||||
if is_str {
|
}) == Some(true);
|
||||||
Applicability::MachineApplicable
|
let debug = !display && cx.tcx.get_diagnostic_item(sym::debug_trait).map(|t| {
|
||||||
} else {
|
infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply()
|
||||||
Applicability::MaybeIncorrect
|
}) == Some(true);
|
||||||
},
|
(display, debug)
|
||||||
);
|
});
|
||||||
if !is_str && panic == sym::std_panic_macro {
|
|
||||||
|
let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
|
||||||
|
|
||||||
|
let fmt_applicability = if suggest_panic_any {
|
||||||
|
// If we can use panic_any, use that as the MachineApplicable suggestion.
|
||||||
|
Applicability::MaybeIncorrect
|
||||||
|
} else {
|
||||||
|
// If we don't suggest panic_any, using a format string is our best bet.
|
||||||
|
Applicability::MachineApplicable
|
||||||
|
};
|
||||||
|
|
||||||
|
if suggest_display {
|
||||||
|
l.span_suggestion_verbose(
|
||||||
|
arg_span.shrink_to_lo(),
|
||||||
|
"add a \"{}\" format string to Display the message",
|
||||||
|
"\"{}\", ".into(),
|
||||||
|
fmt_applicability,
|
||||||
|
);
|
||||||
|
} else if suggest_debug {
|
||||||
|
l.span_suggestion_verbose(
|
||||||
|
arg_span.shrink_to_lo(),
|
||||||
|
&format!(
|
||||||
|
"add a \"{{:?}}\" format string to use the Debug implementation of `{}`",
|
||||||
|
ty,
|
||||||
|
),
|
||||||
|
"\"{:?}\", ".into(),
|
||||||
|
fmt_applicability,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.multipart_suggestion(
|
l.multipart_suggestion(
|
||||||
"or use std::panic::panic_any instead",
|
&format!(
|
||||||
|
"{}use std::panic::panic_any instead",
|
||||||
|
if suggest_display || suggest_debug {
|
||||||
|
"or "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
),
|
||||||
if del == '(' {
|
if del == '(' {
|
||||||
vec![(span.until(open), "std::panic::panic_any".into())]
|
vec![(span.until(open), "std::panic::panic_any".into())]
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user