mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 07:04:18 +00:00
Rewrite the print/write macro checks as a PreExpansionPass
This commit is contained in:
parent
8085ed733f
commit
ff0e5f967f
14 changed files with 256 additions and 364 deletions
|
@ -16,6 +16,7 @@
|
|||
|
||||
use toml;
|
||||
use rustc_plugin;
|
||||
use rustc;
|
||||
|
||||
|
||||
macro_rules! declare_clippy_lint {
|
||||
|
@ -175,6 +176,10 @@ mod reexport {
|
|||
crate use syntax::ast::{Name, NodeId};
|
||||
}
|
||||
|
||||
pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore) {
|
||||
store.register_pre_expansion_pass(Some(session), box write::Pass);
|
||||
}
|
||||
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||
let conf = match utils::conf::file_from_args(reg.args()) {
|
||||
|
@ -320,7 +325,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||
reg.register_late_lint_pass(box strings::StringLitAsBytes);
|
||||
reg.register_late_lint_pass(box derive::Derive);
|
||||
reg.register_late_lint_pass(box types::CharLitAsU8);
|
||||
reg.register_late_lint_pass(box write::Pass);
|
||||
reg.register_late_lint_pass(box vec::Pass);
|
||||
reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames {
|
||||
single_char_binding_names_threshold: conf.single_char_binding_names_threshold,
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
use rustc::hir::map::Node::{NodeImplItem, NodeItem};
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::*;
|
||||
use rustc::{declare_lint, lint_array};
|
||||
use if_chain::if_chain;
|
||||
use std::ops::Deref;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::ptr;
|
||||
use syntax::symbol::LocalInternedString;
|
||||
use syntax_pos::Span;
|
||||
use crate::utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg};
|
||||
use crate::utils::{opt_def_id, paths, last_path_segment};
|
||||
use syntax::ast::*;
|
||||
use syntax::tokenstream::{ThinTokenStream, TokenStream};
|
||||
use syntax::parse::{token, parser};
|
||||
use crate::utils::{span_lint, span_lint_and_sugg};
|
||||
|
||||
/// **What it does:** This lint warns when you use `println!("")` to
|
||||
/// print a newline.
|
||||
|
@ -173,317 +167,149 @@ impl LintPass for Pass {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
match expr.node {
|
||||
// print!()
|
||||
ExprKind::Call(ref fun, ref args) => {
|
||||
if_chain! {
|
||||
if let ExprKind::Path(ref qpath) = fun.node;
|
||||
if let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
|
||||
then {
|
||||
check_print_variants(cx, expr, fun_id, args);
|
||||
}
|
||||
impl EarlyLintPass for Pass {
|
||||
fn check_mac(&mut self, cx: &EarlyContext, mac: &Mac) {
|
||||
if mac.node.path == "println" {
|
||||
span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
|
||||
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
|
||||
if fmtstr == "" {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PRINTLN_EMPTY_STRING,
|
||||
mac.span,
|
||||
"using `println!(\"\")`",
|
||||
"replace it with",
|
||||
"println!()".to_string(),
|
||||
);
|
||||
}
|
||||
},
|
||||
// write!()
|
||||
ExprKind::MethodCall(ref fun, _, ref args) => {
|
||||
if fun.ident.name == "write_fmt" {
|
||||
check_write_variants(cx, expr, args);
|
||||
}
|
||||
} else if mac.node.path == "print" {
|
||||
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
|
||||
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false) {
|
||||
if fmtstr.ends_with("\\n") {
|
||||
span_lint(cx, PRINT_WITH_NEWLINE, mac.span,
|
||||
"using `print!()` with a format string that ends in a \
|
||||
newline, consider using `println!()` instead");
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
} else if mac.node.path == "write" {
|
||||
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
|
||||
if fmtstr.ends_with("\\n") {
|
||||
span_lint(cx, WRITE_WITH_NEWLINE, mac.span,
|
||||
"using `write!()` with a format string that ends in a \
|
||||
newline, consider using `writeln!()` instead");
|
||||
}
|
||||
}
|
||||
} else if mac.node.path == "writeln" {
|
||||
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true) {
|
||||
if fmtstr == "" {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
WRITELN_EMPTY_STRING,
|
||||
mac.span,
|
||||
"using `writeln!(v, \"\")`",
|
||||
"replace it with",
|
||||
"writeln!(v)".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_write_variants<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, write_args: &ptr::P<[Expr]>) {
|
||||
// `writeln!` uses `write!`.
|
||||
if let Some(span) = is_expn_of(expr.span, "write") {
|
||||
let (span, name) = match is_expn_of(span, "writeln") {
|
||||
Some(span) => (span, "writeln"),
|
||||
None => (span, "write"),
|
||||
fn check_tts(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> Option<String> {
|
||||
let tts = TokenStream::from(tts.clone());
|
||||
let mut parser = parser::Parser::new(
|
||||
&cx.sess.parse_sess,
|
||||
tts,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
if is_write {
|
||||
// skip the initial write target
|
||||
parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
|
||||
// might be `writeln!(foo)`
|
||||
parser.expect(&token::Comma).map_err(|mut err| err.cancel()).ok()?;
|
||||
}
|
||||
let fmtstr = parser.parse_str().map_err(|mut err| err.cancel()).ok()?.0.to_string();
|
||||
use fmt_macros::*;
|
||||
let tmp = fmtstr.clone();
|
||||
let mut args = vec![];
|
||||
let mut fmt_parser = Parser::new(&tmp, None);
|
||||
while let Some(piece) = fmt_parser.next() {
|
||||
if !fmt_parser.errors.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if let Piece::NextArgument(arg) = piece {
|
||||
if arg.format.ty == "?" {
|
||||
// FIXME: modify rustc's fmt string parser to give us the current span
|
||||
span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
|
||||
}
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
let lint = if is_write {
|
||||
WRITE_LITERAL
|
||||
} else {
|
||||
PRINT_LITERAL
|
||||
};
|
||||
let mut idx = 0;
|
||||
loop {
|
||||
if !parser.eat(&token::Comma) {
|
||||
assert!(parser.eat(&token::Eof));
|
||||
return Some(fmtstr);
|
||||
}
|
||||
let expr = parser.parse_expr().map_err(|mut err| err.cancel()).ok()?;
|
||||
const SIMPLE: FormatSpec = FormatSpec {
|
||||
fill: None,
|
||||
align: AlignUnknown,
|
||||
flags: 0,
|
||||
precision: CountImplied,
|
||||
width: CountImplied,
|
||||
ty: "",
|
||||
};
|
||||
|
||||
if_chain! {
|
||||
// ensure we're calling Arguments::new_v1 or Arguments::new_v1_formatted
|
||||
if write_args.len() == 2;
|
||||
if let ExprKind::Call(ref args_fun, ref args_args) = write_args[1].node;
|
||||
if let ExprKind::Path(ref qpath) = args_fun.node;
|
||||
if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id));
|
||||
if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1) ||
|
||||
match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED);
|
||||
then {
|
||||
// Check for literals in the write!/writeln! args
|
||||
check_fmt_args_for_literal(cx, args_args, |span| {
|
||||
span_lint(cx, WRITE_LITERAL, span, "writing a literal with an empty format string");
|
||||
});
|
||||
|
||||
if_chain! {
|
||||
if args_args.len() >= 2;
|
||||
if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node;
|
||||
if let ExprKind::Match(ref args, _, _) = match_expr.node;
|
||||
if let ExprKind::Tup(ref args) = args.node;
|
||||
if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]);
|
||||
then {
|
||||
match name {
|
||||
"write" => if has_newline_end(args, fmtstr, fmtlen) {
|
||||
span_lint(cx, WRITE_WITH_NEWLINE, span,
|
||||
"using `write!()` with a format string that ends in a \
|
||||
newline, consider using `writeln!()` instead");
|
||||
match &expr.node {
|
||||
ExprKind::Lit(_) => {
|
||||
let mut all_simple = true;
|
||||
let mut seen = false;
|
||||
for arg in &args {
|
||||
match arg.position {
|
||||
| ArgumentImplicitlyIs(n)
|
||||
| ArgumentIs(n)
|
||||
=> if n == idx {
|
||||
all_simple &= arg.format == SIMPLE;
|
||||
seen = true;
|
||||
},
|
||||
ArgumentNamed(_) => {},
|
||||
}
|
||||
}
|
||||
if all_simple && seen {
|
||||
span_lint(cx, lint, expr.span, "literal with an empty format string");
|
||||
}
|
||||
idx += 1;
|
||||
},
|
||||
ExprKind::Assign(lhs, rhs) => {
|
||||
if let ExprKind::Path(_, p) = &lhs.node {
|
||||
let mut all_simple = true;
|
||||
let mut seen = false;
|
||||
for arg in &args {
|
||||
match arg.position {
|
||||
| ArgumentImplicitlyIs(_)
|
||||
| ArgumentIs(_)
|
||||
=> {},
|
||||
ArgumentNamed(name) => if *p == name {
|
||||
seen = true;
|
||||
all_simple &= arg.format == SIMPLE;
|
||||
},
|
||||
"writeln" => if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
WRITE_WITH_NEWLINE,
|
||||
final_span,
|
||||
"using `writeln!(v, \"\")`",
|
||||
"replace it with",
|
||||
"writeln!(v)".to_string(),
|
||||
);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_print_variants<'a, 'tcx>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
expr: &'tcx Expr,
|
||||
fun_id: def_id::DefId,
|
||||
args: &ptr::P<[Expr]>,
|
||||
) {
|
||||
// Search for `std::io::_print(..)` which is unique in a
|
||||
// `print!` expansion.
|
||||
if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) {
|
||||
if let Some(span) = is_expn_of(expr.span, "print") {
|
||||
// `println!` uses `print!`.
|
||||
let (span, name) = match is_expn_of(span, "println") {
|
||||
Some(span) => (span, "println"),
|
||||
None => (span, "print"),
|
||||
};
|
||||
|
||||
span_lint(cx, PRINT_STDOUT, span, &format!("use of `{}!`", name));
|
||||
if_chain! {
|
||||
// ensure we're calling Arguments::new_v1
|
||||
if args.len() == 1;
|
||||
if let ExprKind::Call(ref args_fun, ref args_args) = args[0].node;
|
||||
then {
|
||||
// Check for literals in the print!/println! args
|
||||
check_fmt_args_for_literal(cx, args_args, |span| {
|
||||
span_lint(cx, PRINT_LITERAL, span, "printing a literal with an empty format string");
|
||||
});
|
||||
|
||||
if_chain! {
|
||||
if let ExprKind::Path(ref qpath) = args_fun.node;
|
||||
if let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id));
|
||||
if match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1);
|
||||
if args_args.len() == 2;
|
||||
if let ExprKind::AddrOf(_, ref match_expr) = args_args[1].node;
|
||||
if let ExprKind::Match(ref args, _, _) = match_expr.node;
|
||||
if let ExprKind::Tup(ref args) = args.node;
|
||||
if let Some((fmtstr, fmtlen)) = get_argument_fmtstr_parts(&args_args[0]);
|
||||
then {
|
||||
match name {
|
||||
"print" =>
|
||||
if has_newline_end(args, fmtstr, fmtlen) {
|
||||
span_lint(cx, PRINT_WITH_NEWLINE, span,
|
||||
"using `print!()` with a format string that ends in a \
|
||||
newline, consider using `println!()` instead");
|
||||
},
|
||||
"println" =>
|
||||
if let Some(final_span) = has_empty_arg(cx, span, fmtstr, fmtlen) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PRINT_WITH_NEWLINE,
|
||||
final_span,
|
||||
"using `println!(\"\")`",
|
||||
"replace it with",
|
||||
"println!()".to_string(),
|
||||
);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if all_simple && seen {
|
||||
span_lint(cx, lint, rhs.span, "literal with an empty format string");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Search for something like
|
||||
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
|
||||
else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
|
||||
if let ExprKind::Path(ref qpath) = args[1].node {
|
||||
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) {
|
||||
if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr)
|
||||
&& is_expn_of(expr.span, "panic").is_none()
|
||||
{
|
||||
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => idx += 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for literals in write!/writeln! and print!/println! args
|
||||
// ensuring the format string for the literal is `DISPLAY_FMT_METHOD`
|
||||
// e.g., `writeln!(buf, "... {} ...", "foo")`
|
||||
// ^ literal in `writeln!`
|
||||
// e.g., `println!("... {} ...", "foo")`
|
||||
// ^ literal in `println!`
|
||||
fn check_fmt_args_for_literal<'a, 'tcx, F>(cx: &LateContext<'a, 'tcx>, args: &HirVec<Expr>, lint_fn: F)
|
||||
where
|
||||
F: Fn(Span),
|
||||
{
|
||||
if_chain! {
|
||||
if args.len() >= 2;
|
||||
|
||||
// the match statement
|
||||
if let ExprKind::AddrOf(_, ref match_expr) = args[1].node;
|
||||
if let ExprKind::Match(ref matchee, ref arms, _) = match_expr.node;
|
||||
if let ExprKind::Tup(ref tup) = matchee.node;
|
||||
if arms.len() == 1;
|
||||
if let ExprKind::Array(ref arm_body_exprs) = arms[0].body.node;
|
||||
then {
|
||||
// it doesn't matter how many args there are in the `write!`/`writeln!`,
|
||||
// if there's one literal, we should warn the user
|
||||
for (idx, tup_arg) in tup.iter().enumerate() {
|
||||
if_chain! {
|
||||
// first, make sure we're dealing with a literal (i.e., an ExprKind::Lit)
|
||||
if let ExprKind::AddrOf(_, ref tup_val) = tup_arg.node;
|
||||
if let ExprKind::Lit(_) = tup_val.node;
|
||||
|
||||
// next, check the corresponding match arm body to ensure
|
||||
// this is DISPLAY_FMT_METHOD
|
||||
if let ExprKind::Call(_, ref body_args) = arm_body_exprs[idx].node;
|
||||
if body_args.len() == 2;
|
||||
if let ExprKind::Path(ref body_qpath) = body_args[1].node;
|
||||
if let Some(fun_def_id) = opt_def_id(resolve_node(cx, body_qpath, body_args[1].hir_id));
|
||||
if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD);
|
||||
then {
|
||||
if args.len() == 2 {
|
||||
lint_fn(tup_val.span);
|
||||
}
|
||||
|
||||
// ensure the format str has no options (e.g., width, precision, alignment, etc.)
|
||||
// and is just "{}"
|
||||
if_chain! {
|
||||
if args.len() == 3;
|
||||
if let ExprKind::AddrOf(_, ref format_expr) = args[2].node;
|
||||
if let ExprKind::Array(ref format_exprs) = format_expr.node;
|
||||
if format_exprs.len() >= 1;
|
||||
if let ExprKind::Struct(_, ref fields, _) = format_exprs[idx].node;
|
||||
if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
|
||||
if check_unformatted(&format_field.expr);
|
||||
then {
|
||||
lint_fn(tup_val.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for fmtstr = "... \n"
|
||||
fn has_newline_end(args: &HirVec<Expr>, fmtstr: LocalInternedString, fmtlen: usize) -> bool {
|
||||
if_chain! {
|
||||
// check the final format string part
|
||||
if let Some('\n') = fmtstr.chars().last();
|
||||
|
||||
// "foo{}bar" is made into two strings + one argument,
|
||||
// if the format string starts with `{}` (eg. "{}foo"),
|
||||
// the string array is prepended an empty string "".
|
||||
// We only want to check the last string after any `{}`:
|
||||
if args.len() < fmtlen;
|
||||
then {
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check for writeln!(v, "") / println!("")
|
||||
fn has_empty_arg<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: LocalInternedString, fmtlen: usize) -> Option<Span> {
|
||||
if_chain! {
|
||||
// check that the string is empty
|
||||
if fmtlen == 1;
|
||||
if fmtstr.deref() == "\n";
|
||||
|
||||
// check the presence of that string
|
||||
if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span);
|
||||
if snippet.contains("\"\"");
|
||||
then {
|
||||
if snippet.ends_with(';') {
|
||||
return Some(cx.sess().codemap().span_until_char(span, ';'));
|
||||
}
|
||||
return Some(span)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the slice of format string parts in an `Arguments::new_v1` call.
|
||||
fn get_argument_fmtstr_parts(expr: &Expr) -> Option<(LocalInternedString, usize)> {
|
||||
if_chain! {
|
||||
if let ExprKind::AddrOf(_, ref expr) = expr.node; // &["…", "…", …]
|
||||
if let ExprKind::Array(ref exprs) = expr.node;
|
||||
if let Some(expr) = exprs.last();
|
||||
if let ExprKind::Lit(ref lit) = expr.node;
|
||||
if let LitKind::Str(ref lit, _) = lit.node;
|
||||
then {
|
||||
return Some((lit.as_str(), exprs.len()));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
|
||||
let map = &cx.tcx.hir;
|
||||
|
||||
// `fmt` method
|
||||
if let Some(NodeImplItem(item)) = map.find(map.get_parent(expr.id)) {
|
||||
// `Debug` impl
|
||||
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
|
||||
if let ItemKind::Impl(_, _, _, _, Some(ref tr), _, _) = item.node {
|
||||
return match_path(&tr.path, &["Debug"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Checks if the expression matches
|
||||
/// ```rust,ignore
|
||||
/// &[_ {
|
||||
/// format: _ {
|
||||
/// width: _::Implied,
|
||||
/// ...
|
||||
/// },
|
||||
/// ...,
|
||||
/// }]
|
||||
/// ```
|
||||
pub fn check_unformatted(format_field: &Expr) -> bool {
|
||||
if_chain! {
|
||||
if let ExprKind::Struct(_, ref fields, _) = format_field.node;
|
||||
if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width");
|
||||
if let ExprKind::Path(ref qpath) = width_field.expr.node;
|
||||
if last_path_segment(qpath).ident.name == "Implied";
|
||||
if let Some(align_field) = fields.iter().find(|f| f.ident.name == "align");
|
||||
if let ExprKind::Path(ref qpath) = align_field.expr.node;
|
||||
if last_path_segment(qpath).ident.name == "Unknown";
|
||||
if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision");
|
||||
if let ExprKind::Path(ref qpath_precision) = precision_field.expr.node;
|
||||
if last_path_segment(qpath_precision).ident.name == "Implied";
|
||||
then {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ pub fn main() {
|
|||
for (name, to) in lint_groups {
|
||||
ls.register_group(Some(sess), true, name, to);
|
||||
}
|
||||
clippy_lints::register_pre_expansion_lints(sess, &mut ls);
|
||||
|
||||
sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
|
||||
sess.plugin_attributes.borrow_mut().extend(attributes);
|
||||
|
|
|
@ -22,7 +22,7 @@ fn main() {
|
|||
const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
|
||||
|
||||
// Literal as param
|
||||
println!("{}", 8.888_888_888_888_888_888_888);
|
||||
println!("{:?}", 8.888_888_888_888_888_888_888);
|
||||
|
||||
// // TODO add inferred type tests for f32
|
||||
// Locals
|
||||
|
|
|
@ -43,10 +43,10 @@ error: float has excessive precision
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
|
||||
|
||||
error: float has excessive precision
|
||||
--> $DIR/excessive_precision.rs:25:20
|
||||
--> $DIR/excessive_precision.rs:25:22
|
||||
|
|
||||
25 | println!("{}", 8.888_888_888_888_888_888_888);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
|
||||
25 | println!("{:?}", 8.888_888_888_888_888_888_888);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
|
||||
|
||||
error: float has excessive precision
|
||||
--> $DIR/excessive_precision.rs:36:22
|
||||
|
|
|
@ -26,6 +26,23 @@ help: instead of prefixing all patterns with `&`, you can dereference the expres
|
|||
32 | None => println!("none"),
|
||||
|
|
||||
|
||||
error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/matches.rs:40:5
|
||||
|
|
||||
40 | / match tup {
|
||||
41 | | &(v, 1) => println!("{}", v),
|
||||
42 | | _ => println!("none"),
|
||||
43 | | }
|
||||
| |_____^
|
||||
help: try this
|
||||
|
|
||||
40 | if let &(v, 1) = tup {
|
||||
41 | # [ cfg ( not ( stage0 ) ) ] {
|
||||
42 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; } # [
|
||||
43 | cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( $ ( $ arg ) * ) ) } } else {
|
||||
44 | ( $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ) ; }
|
||||
|
|
||||
|
||||
error: you don't need to add `&` to all patterns
|
||||
--> $DIR/matches.rs:40:5
|
||||
|
|
||||
|
@ -350,5 +367,5 @@ error: use as_mut() instead
|
|||
221 | | };
|
||||
| |_____^ help: try this: `mut_owned.as_mut()`
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
error: using `println!("")`
|
||||
--> $DIR/non_expressive_names.rs:60:14
|
||||
|
|
||||
60 | _ => println!(""),
|
||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
||||
|
|
||||
= note: `-D println-empty-string` implied by `-D warnings`
|
||||
|
||||
error: using `println!("")`
|
||||
--> $DIR/non_expressive_names.rs:128:18
|
||||
|
|
||||
128 | 1 => println!(""),
|
||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
||||
|
||||
error: using `println!("")`
|
||||
--> $DIR/non_expressive_names.rs:132:18
|
||||
|
|
||||
132 | 1 => println!(""),
|
||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
||||
|
||||
error: binding's name is too similar to existing binding
|
||||
--> $DIR/non_expressive_names.rs:18:9
|
||||
|
|
||||
|
@ -167,5 +187,5 @@ error: consider choosing a more descriptive name
|
|||
151 | let __1___2 = 12;
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
error: use of `Debug`-based formatting
|
||||
--> $DIR/print.rs:13:27
|
||||
--> $DIR/print.rs:13:19
|
||||
|
|
||||
13 | write!(f, "{:?}", 43.1415)
|
||||
| ^^^^^^^
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: `-D use-debug` implied by `-D warnings`
|
||||
|
||||
error: use of `Debug`-based formatting
|
||||
--> $DIR/print.rs:20:19
|
||||
|
|
||||
20 | write!(f, "{:?}", 42.718)
|
||||
| ^^^^^^
|
||||
|
||||
error: use of `println!`
|
||||
--> $DIR/print.rs:25:5
|
||||
|
|
||||
25 | println!("Hello");
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D print-stdout` implied by `-D warnings`
|
||||
|
||||
|
@ -18,37 +24,37 @@ error: use of `print!`
|
|||
--> $DIR/print.rs:26:5
|
||||
|
|
||||
26 | print!("Hello");
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of `print!`
|
||||
--> $DIR/print.rs:28:5
|
||||
|
|
||||
28 | print!("Hello {}", "World");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of `print!`
|
||||
--> $DIR/print.rs:30:5
|
||||
|
|
||||
30 | print!("Hello {:?}", "World");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of `Debug`-based formatting
|
||||
--> $DIR/print.rs:30:26
|
||||
--> $DIR/print.rs:30:12
|
||||
|
|
||||
30 | print!("Hello {:?}", "World");
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: use of `print!`
|
||||
--> $DIR/print.rs:32:5
|
||||
|
|
||||
32 | print!("Hello {:#?}", "#orld");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of `Debug`-based formatting
|
||||
--> $DIR/print.rs:32:27
|
||||
--> $DIR/print.rs:32:12
|
||||
|
|
||||
32 | print!("Hello {:#?}", "#orld");
|
||||
| ^^^^^^^
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:23:71
|
||||
|
|
||||
23 | println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
|
||||
|
@ -6,79 +6,79 @@ error: printing a literal with an empty format string
|
|||
|
|
||||
= note: `-D print-literal` implied by `-D warnings`
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:24:24
|
||||
|
|
||||
24 | print!("Hello {}", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:25:36
|
||||
|
|
||||
25 | println!("Hello {} {}", world, "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:26:26
|
||||
|
|
||||
26 | println!("Hello {}", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:27:30
|
||||
|
|
||||
27 | println!("10 / 4 is {}", 2.5);
|
||||
| ^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:28:28
|
||||
|
|
||||
28 | println!("2 + 1 = {}", 3);
|
||||
| ^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:33:25
|
||||
|
|
||||
33 | println!("{0} {1}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:33:34
|
||||
|
|
||||
33 | println!("{0} {1}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:34:25
|
||||
|
|
||||
34 | println!("{1} {0}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:34:34
|
||||
|
|
||||
34 | println!("{1} {0}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:37:33
|
||||
|
|
||||
37 | println!("{foo} {bar}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:37:46
|
||||
|
|
||||
37 | println!("{foo} {bar}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:38:33
|
||||
|
|
||||
38 | println!("{bar} {foo}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: printing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/print_literal.rs:38:46
|
||||
|
|
||||
38 | println!("{bar} {foo}", foo="hello", bar="world");
|
||||
|
|
|
@ -2,9 +2,27 @@ error: using `print!()` with a format string that ends in a newline, consider us
|
|||
--> $DIR/print_with_newline.rs:7:5
|
||||
|
|
||||
7 | print!("Hello/n");
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D print-with-newline` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead
|
||||
--> $DIR/print_with_newline.rs:8:5
|
||||
|
|
||||
8 | print!("Hello {}/n", "world");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead
|
||||
--> $DIR/print_with_newline.rs:9:5
|
||||
|
|
||||
9 | print!("Hello {} {}/n/n", "world", "#2");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: using `print!()` with a format string that ends in a newline, consider using `println!()` instead
|
||||
--> $DIR/print_with_newline.rs:10:5
|
||||
|
|
||||
10 | print!("{}/n", 1265);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error: using `println!("")`
|
|||
3 | println!("");
|
||||
| ^^^^^^^^^^^^ help: replace it with: `println!()`
|
||||
|
|
||||
= note: `-D print-with-newline` implied by `-D warnings`
|
||||
= note: `-D println-empty-string` implied by `-D warnings`
|
||||
|
||||
error: using `println!("")`
|
||||
--> $DIR/println_empty_string.rs:6:14
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:26:79
|
||||
|
|
||||
26 | writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2);
|
||||
|
@ -6,79 +6,79 @@ error: writing a literal with an empty format string
|
|||
|
|
||||
= note: `-D write-literal` implied by `-D warnings`
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:27:32
|
||||
|
|
||||
27 | write!(&mut v, "Hello {}", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:28:44
|
||||
|
|
||||
28 | writeln!(&mut v, "Hello {} {}", world, "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:29:34
|
||||
|
|
||||
29 | writeln!(&mut v, "Hello {}", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:30:38
|
||||
|
|
||||
30 | writeln!(&mut v, "10 / 4 is {}", 2.5);
|
||||
| ^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:31:36
|
||||
|
|
||||
31 | writeln!(&mut v, "2 + 1 = {}", 3);
|
||||
| ^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:36:33
|
||||
|
|
||||
36 | writeln!(&mut v, "{0} {1}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:36:42
|
||||
|
|
||||
36 | writeln!(&mut v, "{0} {1}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:37:33
|
||||
|
|
||||
37 | writeln!(&mut v, "{1} {0}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:37:42
|
||||
|
|
||||
37 | writeln!(&mut v, "{1} {0}", "hello", "world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:40:41
|
||||
|
|
||||
40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:40:54
|
||||
|
|
||||
40 | writeln!(&mut v, "{foo} {bar}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:41:41
|
||||
|
|
||||
41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world");
|
||||
| ^^^^^^^
|
||||
|
||||
error: writing a literal with an empty format string
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal.rs:41:54
|
||||
|
|
||||
41 | writeln!(&mut v, "{bar} {foo}", foo="hello", bar="world");
|
||||
|
|
|
@ -2,7 +2,7 @@ error: using `write!()` with a format string that ends in a newline, consider us
|
|||
--> $DIR/write_with_newline.rs:10:5
|
||||
|
|
||||
10 | write!(&mut v, "Hello/n");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D write-with-newline` implied by `-D warnings`
|
||||
|
||||
|
@ -10,19 +10,19 @@ error: using `write!()` with a format string that ends in a newline, consider us
|
|||
--> $DIR/write_with_newline.rs:11:5
|
||||
|
|
||||
11 | write!(&mut v, "Hello {}/n", "world");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead
|
||||
--> $DIR/write_with_newline.rs:12:5
|
||||
|
|
||||
12 | write!(&mut v, "Hello {} {}/n/n", "world", "#2");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: using `write!()` with a format string that ends in a newline, consider using `writeln!()` instead
|
||||
--> $DIR/write_with_newline.rs:13:5
|
||||
|
|
||||
13 | write!(&mut v, "{}/n", 1265);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error: using `writeln!(v, "")`
|
|||
9 | writeln!(&mut v, "");
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)`
|
||||
|
|
||||
= note: `-D write-with-newline` implied by `-D warnings`
|
||||
= note: `-D writeln-empty-string` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Reference in a new issue