};
if implements_trait(cx, arg_ty, default_trait_id, Vec::new()) {
- span_lint(cx,
+ span_lint_and_then(cx,
OR_FUN_CALL,
span,
- &format!("use of `{}` followed by a call to `{}`", name, path))
- .span_suggestion(span,
- "try this",
- format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")));
+ &format!("use of `{}` followed by a call to `{}`", name, path),
+ |db| {
+ db.span_suggestion(span, "try this",
+ format!("{}.unwrap_or_default()", snippet(cx, self_expr.span, "_")));
+ });
return true;
}
}
(false, true) => snippet(cx, fun.span, ".."),
};
- span_lint(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name))
- .span_suggestion(span,
- "try this",
- format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg));
+ span_lint_and_then(cx, OR_FUN_CALL, span, &format!("use of `{}` followed by a function call", name), |db| {
+ db.span_suggestion(span,
+ "try this",
+ format!("{}.{}_{}({})", snippet(cx, self_expr.span, "_"), name, suffix, sugg));
+ });
}
if args.len() == 2 {
fn lint_clone_double_ref(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, ty: ty::Ty) {
if let ty::TyRef(_, ty::TypeAndMut { ty: ref inner, .. }) = ty.sty {
if let ty::TyRef(..) = inner.sty {
- let mut db = span_lint(cx,
- CLONE_DOUBLE_REF,
- expr.span,
- "using `clone` on a double-reference; \
- this will copy the reference instead of cloning \
- the inner type");
- if let Some(snip) = snippet_opt(cx, arg.span) {
- db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip));
- }
+ span_lint_and_then(cx,
+ CLONE_DOUBLE_REF,
+ expr.span,
+ "using `clone` on a double-reference; \
+ this will copy the reference instead of cloning the inner type",
+ |db| if let Some(snip) = snippet_opt(cx, arg.span) {
+ db.span_suggestion(expr.span, "try dereferencing it", format!("(*{}).clone()", snip));
+ });
}
}
}
}
let arg_ty = cx.tcx.expr_ty(&args[1]);
if let Some((span, r)) = derefs_to_slice(cx, &args[1], &arg_ty) {
- span_lint(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice")
- .span_suggestion(expr.span,
- "try this",
- format!("{}.extend_from_slice({}{})",
- snippet(cx, args[0].span, "_"),
- r,
- snippet(cx, span, "_")));
+ span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
+ db.span_suggestion(expr.span,
+ "try this",
+ format!("{}.extend_from_slice({}{})",
+ snippet(cx, args[0].span, "_"),
+ r,
+ snippet(cx, span, "_")));
+ });
}
}
use syntax::ast;
use syntax::codemap::Span;
use utils::paths;
-use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint};
+use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
/// **What it does:** This lints about type with a `fn new() -> Self` method
/// and no implementation of
!implements_trait(cx, self_ty, default_trait_id, Vec::new())
], {
if can_derive_default(self_ty, cx, default_trait_id) {
- span_lint(cx,
- NEW_WITHOUT_DEFAULT_DERIVE, span,
- &format!("you should consider deriving a \
- `Default` implementation for `{}`",
- self_ty)).
- span_suggestion(span,
- "try this",
- "#[derive(Default)]".into());
+ span_lint_and_then(cx,
+ NEW_WITHOUT_DEFAULT_DERIVE, span,
+ &format!("you should consider deriving a \
+ `Default` implementation for `{}`",
+ self_ty),
+ |db| {
+ db.span_suggestion(span, "try this", "#[derive(Default)]".into());
+ });
} else {
- span_lint(cx,
- NEW_WITHOUT_DEFAULT, span,
- &format!("you should consider adding a \
- `Default` implementation for `{}`",
- self_ty)).
- span_suggestion(span,
- "try this",
- format!("impl Default for {} {{ fn default() -> \
- Self {{ {}::new() }} }}", self_ty, self_ty));
+ span_lint_and_then(cx,
+ NEW_WITHOUT_DEFAULT, span,
+ &format!("you should consider adding a \
+ `Default` implementation for `{}`",
+ self_ty),
+ |db| {
+ db.span_suggestion(span,
+ "try this",
+ format!("impl Default for {} {{ fn default() -> \
+ Self {{ {}::new() }} }}", self_ty, self_ty));
+ });
}
}}
}
use rustc::hir::intravisit::{Visitor, FnKind};
use std::ops::Deref;
use syntax::codemap::Span;
-use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper};
+use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint_and_then};
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability.
///
fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span)
where T: Deref<Target = Expr>
{
- fn note_orig(cx: &LateContext, mut db: DiagnosticWrapper, lint: &'static Lint, span: Span) {
- if cx.current_level(lint) != Level::Allow {
- db.span_note(span, "previous binding is here");
- }
- }
if let Some(ref expr) = *init {
if is_self_shadow(name, expr) {
- let db = span_lint(cx,
+ span_lint_and_then(cx,
SHADOW_SAME,
span,
&format!("`{}` is shadowed by itself in `{}`",
snippet(cx, pattern_span, "_"),
- snippet(cx, expr.span, "..")));
-
- note_orig(cx, db, SHADOW_SAME, prev_span);
+ snippet(cx, expr.span, "..")),
+ |db| { db.span_note(prev_span, "previous binding is here"); },
+ );
} else if contains_self(name, expr) {
- let db = span_note_and_lint(cx,
- SHADOW_REUSE,
- pattern_span,
- &format!("`{}` is shadowed by `{}` which reuses the original value",
- snippet(cx, pattern_span, "_"),
- snippet(cx, expr.span, "..")),
- expr.span,
- "initialization happens here");
- note_orig(cx, db, SHADOW_REUSE, prev_span);
+ span_lint_and_then(cx,
+ SHADOW_REUSE,
+ pattern_span,
+ &format!("`{}` is shadowed by `{}` which reuses the original value",
+ snippet(cx, pattern_span, "_"),
+ snippet(cx, expr.span, "..")),
+ |db| {
+ db.span_note(expr.span, "initialization happens here");
+ db.span_note(prev_span, "previous binding is here");
+ });
} else {
- let db = span_note_and_lint(cx,
- SHADOW_UNRELATED,
- pattern_span,
- &format!("`{}` is shadowed by `{}`",
- snippet(cx, pattern_span, "_"),
- snippet(cx, expr.span, "..")),
- expr.span,
- "initialization happens here");
- note_orig(cx, db, SHADOW_UNRELATED, prev_span);
+ span_lint_and_then(cx,
+ SHADOW_UNRELATED,
+ pattern_span,
+ &format!("`{}` is shadowed by `{}`",
+ snippet(cx, pattern_span, "_"),
+ snippet(cx, expr.span, "..")),
+ |db| {
+ db.span_note(expr.span, "initialization happens here");
+ db.span_note(prev_span, "previous binding is here");
+ });
}
} else {
- let db = span_lint(cx,
+ span_lint_and_then(cx,
SHADOW_UNRELATED,
span,
- &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")));
- note_orig(cx, db, SHADOW_UNRELATED, prev_span);
+ &format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")),
+ |db| { db.span_note(prev_span, "previous binding is here"); });
}
}
use std::borrow::Cow;
use std::env;
use std::mem;
-use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use syntax::ast::{self, LitKind, RangeLimits};
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
}
}
-impl<'a> DerefMut for DiagnosticWrapper<'a> {
- fn deref_mut(&mut self) -> &mut DiagnosticBuilder<'a> {
- &mut self.0
- }
-}
-
-impl<'a> Deref for DiagnosticWrapper<'a> {
- type Target = DiagnosticBuilder<'a>;
- fn deref(&self) -> &DiagnosticBuilder<'a> {
- &self.0
- }
-}
-
impl<'a> DiagnosticWrapper<'a> {
fn wiki_link(&mut self, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_WIKI_LINKS").is_err() {
- self.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}",
+ self.0.help(&format!("for further information visit https://github.com/Manishearth/rust-clippy/wiki#{}",
lint.name_lower()));
}
}
}
-pub fn span_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str) -> DiagnosticWrapper<'a> {
+pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
if cx.current_level(lint) != Level::Allow {
db.wiki_link(lint);
}
- db
}
-pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str)
- -> DiagnosticWrapper<'a> {
+// FIXME: needless lifetime doesn't trigger here
+pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
if cx.current_level(lint) != Level::Allow {
- db.help(help);
+ db.0.help(help);
db.wiki_link(lint);
}
- db
}
pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span,
- note: &str)
- -> DiagnosticWrapper<'a> {
+ note: &str) {
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
if cx.current_level(lint) != Level::Allow {
if note_span == span {
- db.note(note);
+ db.0.note(note);
} else {
- db.span_note(note_span, note);
+ db.0.span_note(note_span, note);
}
db.wiki_link(lint);
}
- db
}
pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
- -> DiagnosticWrapper<'a>
- where F: FnOnce(&mut DiagnosticWrapper)
+ where F: FnOnce(&mut DiagnosticBuilder<'a>)
{
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
if cx.current_level(lint) != Level::Allow {
- f(&mut db);
+ f(&mut db.0);
db.wiki_link(lint);
}
- db
}
/// Return the base type for references and raw pointers.