summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_lint/src/unused.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_lint/src/unused.rs255
1 files changed, 136 insertions, 119 deletions
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index b6cf18291..46706e498 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -7,11 +7,12 @@ use rustc_errors::{fluent, pluralize, Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
+use rustc_infer::traits::util::elaborate_predicates_with_span;
use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{kw, sym};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, Span};
declare_lint! {
/// The `unused_must_use` lint detects unused result of a type flagged as
@@ -154,24 +155,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
};
if let Some(must_use_op) = must_use_op {
- cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| {
- lint.build(fluent::lint::unused_op)
- .set_arg("op", must_use_op)
- .span_label(expr.span, fluent::lint::label)
+ cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| {
+ lint.set_arg("op", must_use_op)
+ .span_label(expr.span, fluent::label)
.span_suggestion_verbose(
expr.span.shrink_to_lo(),
- fluent::lint::suggestion,
+ fluent::suggestion,
"let _ = ",
Applicability::MachineApplicable,
)
- .emit();
});
op_warned = true;
}
if !(type_permits_lack_of_use || fn_warned || op_warned) {
- cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
- lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit();
+ cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| {
+ lint.set_arg("ty", ty)
});
}
@@ -206,10 +205,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
ty::Opaque(def, _) => {
let mut has_emitted = false;
- for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
+ for obligation in elaborate_predicates_with_span(
+ cx.tcx,
+ cx.tcx.explicit_item_bounds(def).iter().cloned(),
+ ) {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
- predicate.kind().skip_binder()
+ obligation.predicate.kind().skip_binder()
{
let def_id = poly_trait_predicate.trait_ref.def_id;
let descr_pre =
@@ -222,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
has_emitted
}
- ty::Dynamic(binder, _) => {
+ ty::Dynamic(binder, _, _) => {
let mut has_emitted = false;
for predicate in binder.iter() {
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
@@ -267,29 +269,35 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
},
ty::Closure(..) => {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
- // FIXME(davidtwco): this isn't properly translatable becauses of the
- // pre/post strings
- lint.build(fluent::lint::unused_closure)
- .set_arg("count", plural_len)
- .set_arg("pre", descr_pre)
- .set_arg("post", descr_post)
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ UNUSED_MUST_USE,
+ span,
+ fluent::lint_unused_closure,
+ |lint| {
+ // FIXME(davidtwco): this isn't properly translatable because of the
+ // pre/post strings
+ lint.set_arg("count", plural_len)
+ .set_arg("pre", descr_pre)
+ .set_arg("post", descr_post)
+ .note(fluent::note)
+ },
+ );
true
}
ty::Generator(..) => {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
- // FIXME(davidtwco): this isn't properly translatable becauses of the
- // pre/post strings
- lint.build(fluent::lint::unused_generator)
- .set_arg("count", plural_len)
- .set_arg("pre", descr_pre)
- .set_arg("post", descr_post)
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ UNUSED_MUST_USE,
+ span,
+ fluent::lint_unused_generator,
+ |lint| {
+ // FIXME(davidtwco): this isn't properly translatable because of the
+ // pre/post strings
+ lint.set_arg("count", plural_len)
+ .set_arg("pre", descr_pre)
+ .set_arg("post", descr_post)
+ .note(fluent::note)
+ },
+ );
true
}
_ => false,
@@ -309,18 +317,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post_path: &str,
) -> bool {
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
- // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
+ 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
// strings
- let mut err = lint.build(fluent::lint::unused_def);
- err.set_arg("pre", descr_pre_path);
- err.set_arg("post", descr_post_path);
- err.set_arg("def", cx.tcx.def_path_str(def_id));
+ lint.set_arg("pre", descr_pre_path);
+ lint.set_arg("post", descr_post_path);
+ lint.set_arg("def", cx.tcx.def_path_str(def_id));
// check for #[must_use = "..."]
if let Some(note) = attr.value_str() {
- err.note(note.as_str());
+ lint.note(note.as_str());
}
- err.emit();
+ lint
});
true
} else {
@@ -357,25 +364,34 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
if let hir::StmtKind::Semi(expr) = s.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);
- if ty.needs_drop(cx.tcx, cx.param_env) {
- let mut lint = lint.build(fluent::lint::path_statement_drop);
- if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
- lint.span_suggestion(
- s.span,
- fluent::lint::suggestion,
- format!("drop({});", snippet),
- Applicability::MachineApplicable,
- );
- } else {
- lint.span_help(s.span, fluent::lint::suggestion);
- }
- lint.emit();
- } else {
- lint.build(fluent::lint::path_statement_no_effect).emit();
- }
- });
+ let ty = cx.typeck_results().expr_ty(expr);
+ if ty.needs_drop(cx.tcx, cx.param_env) {
+ cx.struct_span_lint(
+ PATH_STATEMENTS,
+ s.span,
+ fluent::lint_path_statement_drop,
+ |lint| {
+ if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
+ lint.span_suggestion(
+ s.span,
+ fluent::suggestion,
+ format!("drop({});", snippet),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ lint.span_help(s.span, fluent::suggestion);
+ }
+ lint
+ },
+ );
+ } else {
+ cx.struct_span_lint(
+ PATH_STATEMENTS,
+ s.span,
+ fluent::lint_path_statement_no_effect,
+ |lint| lint,
+ );
+ }
}
}
}
@@ -504,23 +520,23 @@ trait UnusedDelimLint {
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
let start = block.stmts[0].span;
let end = block.stmts[block.stmts.len() - 1].span;
- if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
- (
- value.span.with_hi(value.span.lo() + BytePos(1)),
- value.span.with_lo(value.span.hi() - BytePos(1)),
- )
+ if let Some(start) = start.find_ancestor_inside(value.span)
+ && let Some(end) = end.find_ancestor_inside(value.span)
+ {
+ Some((
+ value.span.with_hi(start.lo()),
+ value.span.with_lo(end.hi()),
+ ))
} else {
- (value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
+ None
}
}
ast::ExprKind::Paren(ref expr) => {
- if value.span.from_expansion() || expr.span.from_expansion() {
- (
- value.span.with_hi(value.span.lo() + BytePos(1)),
- value.span.with_lo(value.span.hi() - BytePos(1)),
- )
+ let expr_span = expr.span.find_ancestor_inside(value.span);
+ if let Some(expr_span) = expr_span {
+ Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
} else {
- (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
+ None
}
}
_ => return,
@@ -529,36 +545,37 @@ trait UnusedDelimLint {
left_pos.map_or(false, |s| s >= value.span.lo()),
right_pos.map_or(false, |s| s <= value.span.hi()),
);
- self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
+ self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
}
fn emit_unused_delims(
&self,
cx: &EarlyContext<'_>,
- spans: (Span, Span),
+ value_span: Span,
+ spans: Option<(Span, Span)>,
msg: &str,
keep_space: (bool, bool),
) {
- // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
- // properly.
- if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
- return;
- }
-
- cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
- let replacement = vec![
- (spans.0, if keep_space.0 { " ".into() } else { "".into() }),
- (spans.1, if keep_space.1 { " ".into() } else { "".into() }),
- ];
- lint.build(fluent::lint::unused_delim)
- .set_arg("delim", Self::DELIM_STR)
- .set_arg("item", msg)
- .multipart_suggestion(
- fluent::lint::suggestion,
+ let primary_span = if let Some((lo, hi)) = spans {
+ MultiSpan::from(vec![lo, hi])
+ } else {
+ MultiSpan::from(value_span)
+ };
+ cx.struct_span_lint(self.lint(), primary_span, fluent::lint_unused_delim, |lint| {
+ lint.set_arg("delim", Self::DELIM_STR);
+ lint.set_arg("item", msg);
+ if let Some((lo, hi)) = spans {
+ let replacement = vec![
+ (lo, if keep_space.0 { " ".into() } else { "".into() }),
+ (hi, if keep_space.1 { " ".into() } else { "".into() }),
+ ];
+ lint.multipart_suggestion(
+ fluent::suggestion,
replacement,
Applicability::MachineApplicable,
- )
- .emit();
+ );
+ }
+ lint
});
}
@@ -606,8 +623,7 @@ trait UnusedDelimLint {
ref call_or_other => {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
- // first "argument" is self (which sometimes needs delims)
- MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
+ MethodCall(_, _, ref args, _) => (&args[..], UnusedDelimsCtx::MethodArg),
// actual catch-all arm
_ => {
return;
@@ -750,7 +766,7 @@ impl UnusedParens {
avoid_or: bool,
avoid_mut: bool,
) {
- use ast::{BindingMode, Mutability, PatKind};
+ use ast::{BindingAnnotation, PatKind};
if let PatKind::Paren(inner) = &value.kind {
match inner.kind {
@@ -762,19 +778,18 @@ impl UnusedParens {
// Avoid `p0 | .. | pn` if we should.
PatKind::Or(..) if avoid_or => return,
// Avoid `mut x` and `mut x @ p` if we should:
- PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return,
+ PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
+ return;
+ }
// Otherwise proceed with linting.
_ => {}
}
- let spans = if value.span.from_expansion() || inner.span.from_expansion() {
- (
- value.span.with_hi(value.span.lo() + BytePos(1)),
- value.span.with_lo(value.span.hi() - BytePos(1)),
- )
+ let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
+ Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
} else {
- (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
+ None
};
- self.emit_unused_delims(cx, spans, "pattern", (false, false));
+ self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
}
}
}
@@ -879,15 +894,12 @@ impl EarlyLintPass for UnusedParens {
);
}
_ => {
- let spans = if ty.span.from_expansion() || r.span.from_expansion() {
- (
- ty.span.with_hi(ty.span.lo() + BytePos(1)),
- ty.span.with_lo(ty.span.hi() - BytePos(1)),
- )
+ let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
+ Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
} else {
- (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
+ None
};
- self.emit_unused_delims(cx, spans, "type", (false, false));
+ self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
}
}
}
@@ -1131,9 +1143,12 @@ impl UnusedImportBraces {
ast::UseTreeKind::Nested(_) => return,
};
- cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
- lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit();
- });
+ cx.struct_span_lint(
+ UNUSED_IMPORT_BRACES,
+ item.span,
+ fluent::lint_unused_import_braces,
+ |lint| lint.set_arg("node", node_name),
+ );
}
}
}
@@ -1182,15 +1197,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
for adj in cx.typeck_results().expr_adjustments(e) {
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
- cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| {
- lint.build(match m {
- adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
+ cx.struct_span_lint(
+ UNUSED_ALLOCATION,
+ e.span,
+ match m {
+ adjustment::AutoBorrowMutability::Not => fluent::lint_unused_allocation,
adjustment::AutoBorrowMutability::Mut { .. } => {
- fluent::lint::unused_allocation_mut
+ fluent::lint_unused_allocation_mut
}
- })
- .emit();
- });
+ },
+ |lint| lint,
+ );
}
}
}