]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/unused.rs
Migrate `rustc_parse` to derive diagnostics
[rust.git] / compiler / rustc_lint / src / unused.rs
1 use crate::lints::{
2     PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
3     UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion,
4     UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
5 };
6 use crate::Lint;
7 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
8 use rustc_ast as ast;
9 use rustc_ast::util::{classify, parser};
10 use rustc_ast::{ExprKind, StmtKind};
11 use rustc_errors::{pluralize, MultiSpan};
12 use rustc_hir as hir;
13 use rustc_hir::def::{DefKind, Res};
14 use rustc_hir::def_id::DefId;
15 use rustc_infer::traits::util::elaborate_predicates_with_span;
16 use rustc_middle::ty::adjustment;
17 use rustc_middle::ty::{self, DefIdTree, Ty};
18 use rustc_span::symbol::Symbol;
19 use rustc_span::symbol::{kw, sym};
20 use rustc_span::{BytePos, Span};
21 use std::iter;
22
23 declare_lint! {
24     /// The `unused_must_use` lint detects unused result of a type flagged as
25     /// `#[must_use]`.
26     ///
27     /// ### Example
28     ///
29     /// ```rust
30     /// fn returns_result() -> Result<(), ()> {
31     ///     Ok(())
32     /// }
33     ///
34     /// fn main() {
35     ///     returns_result();
36     /// }
37     /// ```
38     ///
39     /// {{produces}}
40     ///
41     /// ### Explanation
42     ///
43     /// The `#[must_use]` attribute is an indicator that it is a mistake to
44     /// ignore the value. See [the reference] for more details.
45     ///
46     /// [the reference]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
47     pub UNUSED_MUST_USE,
48     Warn,
49     "unused result of a type flagged as `#[must_use]`",
50     report_in_external_macro
51 }
52
53 declare_lint! {
54     /// The `unused_results` lint checks for the unused result of an
55     /// expression in a statement.
56     ///
57     /// ### Example
58     ///
59     /// ```rust,compile_fail
60     /// #![deny(unused_results)]
61     /// fn foo<T>() -> T { panic!() }
62     ///
63     /// fn main() {
64     ///     foo::<usize>();
65     /// }
66     /// ```
67     ///
68     /// {{produces}}
69     ///
70     /// ### Explanation
71     ///
72     /// Ignoring the return value of a function may indicate a mistake. In
73     /// cases were it is almost certain that the result should be used, it is
74     /// recommended to annotate the function with the [`must_use` attribute].
75     /// Failure to use such a return value will trigger the [`unused_must_use`
76     /// lint] which is warn-by-default. The `unused_results` lint is
77     /// essentially the same, but triggers for *all* return values.
78     ///
79     /// This lint is "allow" by default because it can be noisy, and may not be
80     /// an actual problem. For example, calling the `remove` method of a `Vec`
81     /// or `HashMap` returns the previous value, which you may not care about.
82     /// Using this lint would require explicitly ignoring or discarding such
83     /// values.
84     ///
85     /// [`must_use` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
86     /// [`unused_must_use` lint]: warn-by-default.html#unused-must-use
87     pub UNUSED_RESULTS,
88     Allow,
89     "unused result of an expression in a statement"
90 }
91
92 declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
93
94 impl<'tcx> LateLintPass<'tcx> for UnusedResults {
95     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
96         let hir::StmtKind::Semi(expr) = s.kind else { return; };
97
98         if let hir::ExprKind::Ret(..) = expr.kind {
99             return;
100         }
101
102         if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
103             && let ty = cx.typeck_results().expr_ty(&await_expr)
104             && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
105             && cx.tcx.ty_is_opaque_future(ty)
106             // FIXME: This also includes non-async fns that return `impl Future`.
107             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
108             && check_must_use_def(
109                 cx,
110                 async_fn_def_id,
111                 expr.span,
112                 "output of future returned by ",
113                 "",
114             )
115         {
116             // We have a bare `foo().await;` on an opaque type from an async function that was
117             // annotated with `#[must_use]`.
118             return;
119         }
120
121         let ty = cx.typeck_results().expr_ty(&expr);
122
123         let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
124         let type_lint_emitted_or_suppressed = match must_use_result {
125             Some(path) => {
126                 emit_must_use_untranslated(cx, &path, "", "", 1);
127                 true
128             }
129             None => false,
130         };
131
132         let fn_warned = check_fn_must_use(cx, expr);
133
134         if !fn_warned && type_lint_emitted_or_suppressed {
135             // We don't warn about unused unit or uninhabited types.
136             // (See https://github.com/rust-lang/rust/issues/43806 for details.)
137             return;
138         }
139
140         let must_use_op = match expr.kind {
141             // Hardcoding operators here seemed more expedient than the
142             // refactoring that would be needed to look up the `#[must_use]`
143             // attribute which does exist on the comparison trait methods
144             hir::ExprKind::Binary(bin_op, ..) => match bin_op.node {
145                 hir::BinOpKind::Eq
146                 | hir::BinOpKind::Lt
147                 | hir::BinOpKind::Le
148                 | hir::BinOpKind::Ne
149                 | hir::BinOpKind::Ge
150                 | hir::BinOpKind::Gt => Some("comparison"),
151                 hir::BinOpKind::Add
152                 | hir::BinOpKind::Sub
153                 | hir::BinOpKind::Div
154                 | hir::BinOpKind::Mul
155                 | hir::BinOpKind::Rem => Some("arithmetic operation"),
156                 hir::BinOpKind::And | hir::BinOpKind::Or => Some("logical operation"),
157                 hir::BinOpKind::BitXor
158                 | hir::BinOpKind::BitAnd
159                 | hir::BinOpKind::BitOr
160                 | hir::BinOpKind::Shl
161                 | hir::BinOpKind::Shr => Some("bitwise operation"),
162             },
163             hir::ExprKind::AddrOf(..) => Some("borrow"),
164             hir::ExprKind::Unary(..) => Some("unary operation"),
165             _ => None,
166         };
167
168         let mut op_warned = false;
169
170         if let Some(must_use_op) = must_use_op {
171             cx.emit_spanned_lint(
172                 UNUSED_MUST_USE,
173                 expr.span,
174                 UnusedOp {
175                     op: must_use_op,
176                     label: expr.span,
177                     suggestion: expr.span.shrink_to_lo(),
178                 },
179             );
180             op_warned = true;
181         }
182
183         if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
184             cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
185         }
186
187         fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
188             let maybe_def_id = match expr.kind {
189                 hir::ExprKind::Call(ref callee, _) => {
190                     match callee.kind {
191                         hir::ExprKind::Path(ref qpath) => {
192                             match cx.qpath_res(qpath, callee.hir_id) {
193                                 Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
194                                 // `Res::Local` if it was a closure, for which we
195                                 // do not currently support must-use linting
196                                 _ => None,
197                             }
198                         }
199                         _ => None,
200                     }
201                 }
202                 hir::ExprKind::MethodCall(..) => {
203                     cx.typeck_results().type_dependent_def_id(expr.hir_id)
204                 }
205                 _ => None,
206             };
207             if let Some(def_id) = maybe_def_id {
208                 check_must_use_def(cx, def_id, expr.span, "return value of ", "")
209             } else {
210                 false
211             }
212         }
213
214         /// A path through a type to a must_use source. Contains useful info for the lint.
215         #[derive(Debug)]
216         enum MustUsePath {
217             /// Suppress must_use checking.
218             Suppressed,
219             /// The root of the normal must_use lint with an optional message.
220             Def(Span, DefId, Option<Symbol>),
221             Boxed(Box<Self>),
222             Opaque(Box<Self>),
223             TraitObject(Box<Self>),
224             TupleElement(Vec<(usize, Self)>),
225             Array(Box<Self>, u64),
226             /// The root of the unused_closures lint.
227             Closure(Span),
228             /// The root of the unused_generators lint.
229             Generator(Span),
230         }
231
232         #[instrument(skip(cx, expr), level = "debug", ret)]
233         fn is_ty_must_use<'tcx>(
234             cx: &LateContext<'tcx>,
235             ty: Ty<'tcx>,
236             expr: &hir::Expr<'_>,
237             span: Span,
238         ) -> Option<MustUsePath> {
239             if ty.is_unit()
240                 || !ty.is_inhabited_from(
241                     cx.tcx,
242                     cx.tcx.parent_module(expr.hir_id).to_def_id(),
243                     cx.param_env,
244                 )
245             {
246                 return Some(MustUsePath::Suppressed);
247             }
248
249             match *ty.kind() {
250                 ty::Adt(..) if ty.is_box() => {
251                     let boxed_ty = ty.boxed_ty();
252                     is_ty_must_use(cx, boxed_ty, expr, span)
253                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
254                 }
255                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
256                 ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
257                     elaborate_predicates_with_span(
258                         cx.tcx,
259                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
260                     )
261                     .find_map(|obligation| {
262                         // We only look at the `DefId`, so it is safe to skip the binder here.
263                         if let ty::PredicateKind::Clause(ty::Clause::Trait(
264                             ref poly_trait_predicate,
265                         )) = obligation.predicate.kind().skip_binder()
266                         {
267                             let def_id = poly_trait_predicate.trait_ref.def_id;
268
269                             is_def_must_use(cx, def_id, span)
270                         } else {
271                             None
272                         }
273                     })
274                     .map(|inner| MustUsePath::Opaque(Box::new(inner)))
275                 }
276                 ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
277                     if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
278                     {
279                         let def_id = trait_ref.def_id;
280                         is_def_must_use(cx, def_id, span)
281                             .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
282                     } else {
283                         None
284                     }
285                 }),
286                 ty::Tuple(tys) => {
287                     let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
288                         debug_assert_eq!(elem_exprs.len(), tys.len());
289                         elem_exprs
290                     } else {
291                         &[]
292                     };
293
294                     // Default to `expr`.
295                     let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));
296
297                     let nested_must_use = tys
298                         .iter()
299                         .zip(elem_exprs)
300                         .enumerate()
301                         .filter_map(|(i, (ty, expr))| {
302                             is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
303                         })
304                         .collect::<Vec<_>>();
305
306                     if !nested_must_use.is_empty() {
307                         Some(MustUsePath::TupleElement(nested_must_use))
308                     } else {
309                         None
310                     }
311                 }
312                 ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
313                     // If the array is empty we don't lint, to avoid false positives
314                     Some(0) | None => None,
315                     // If the array is definitely non-empty, we can do `#[must_use]` checking.
316                     Some(len) => is_ty_must_use(cx, ty, expr, span)
317                         .map(|inner| MustUsePath::Array(Box::new(inner), len)),
318                 },
319                 ty::Closure(..) => Some(MustUsePath::Closure(span)),
320                 ty::Generator(def_id, ..) => {
321                     // async fn should be treated as "implementor of `Future`"
322                     let must_use = if cx.tcx.generator_is_async(def_id) {
323                         let def_id = cx.tcx.lang_items().future_trait().unwrap();
324                         is_def_must_use(cx, def_id, span)
325                             .map(|inner| MustUsePath::Opaque(Box::new(inner)))
326                     } else {
327                         None
328                     };
329                     must_use.or(Some(MustUsePath::Generator(span)))
330                 }
331                 _ => None,
332             }
333         }
334
335         fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
336             if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
337                 // check for #[must_use = "..."]
338                 let reason = attr.value_str();
339                 Some(MustUsePath::Def(span, def_id, reason))
340             } else {
341                 None
342             }
343         }
344
345         // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored.
346         fn check_must_use_def(
347             cx: &LateContext<'_>,
348             def_id: DefId,
349             span: Span,
350             descr_pre_path: &str,
351             descr_post_path: &str,
352         ) -> bool {
353             is_def_must_use(cx, def_id, span)
354                 .map(|must_use_path| {
355                     emit_must_use_untranslated(
356                         cx,
357                         &must_use_path,
358                         descr_pre_path,
359                         descr_post_path,
360                         1,
361                     )
362                 })
363                 .is_some()
364         }
365
366         #[instrument(skip(cx), level = "debug")]
367         fn emit_must_use_untranslated(
368             cx: &LateContext<'_>,
369             path: &MustUsePath,
370             descr_pre: &str,
371             descr_post: &str,
372             plural_len: usize,
373         ) {
374             let plural_suffix = pluralize!(plural_len);
375
376             match path {
377                 MustUsePath::Suppressed => {}
378                 MustUsePath::Boxed(path) => {
379                     let descr_pre = &format!("{}boxed ", descr_pre);
380                     emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
381                 }
382                 MustUsePath::Opaque(path) => {
383                     let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
384                     emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
385                 }
386                 MustUsePath::TraitObject(path) => {
387                     let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
388                     emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
389                 }
390                 MustUsePath::TupleElement(elems) => {
391                     for (index, path) in elems {
392                         let descr_post = &format!(" in tuple element {}", index);
393                         emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len);
394                     }
395                 }
396                 MustUsePath::Array(path, len) => {
397                     let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix);
398                     emit_must_use_untranslated(
399                         cx,
400                         path,
401                         descr_pre,
402                         descr_post,
403                         plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
404                     );
405                 }
406                 MustUsePath::Closure(span) => {
407                     cx.emit_spanned_lint(
408                         UNUSED_MUST_USE,
409                         *span,
410                         UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
411                     );
412                 }
413                 MustUsePath::Generator(span) => {
414                     cx.emit_spanned_lint(
415                         UNUSED_MUST_USE,
416                         *span,
417                         UnusedGenerator { count: plural_len, pre: descr_pre, post: descr_post },
418                     );
419                 }
420                 MustUsePath::Def(span, def_id, reason) => {
421                     cx.emit_spanned_lint(
422                         UNUSED_MUST_USE,
423                         *span,
424                         UnusedDef {
425                             pre: descr_pre,
426                             post: descr_post,
427                             cx,
428                             def_id: *def_id,
429                             note: *reason,
430                         },
431                     );
432                 }
433             }
434         }
435     }
436 }
437
438 declare_lint! {
439     /// The `path_statements` lint detects path statements with no effect.
440     ///
441     /// ### Example
442     ///
443     /// ```rust
444     /// let x = 42;
445     ///
446     /// x;
447     /// ```
448     ///
449     /// {{produces}}
450     ///
451     /// ### Explanation
452     ///
453     /// It is usually a mistake to have a statement that has no effect.
454     pub PATH_STATEMENTS,
455     Warn,
456     "path statements with no effect"
457 }
458
459 declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
460
461 impl<'tcx> LateLintPass<'tcx> for PathStatements {
462     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
463         if let hir::StmtKind::Semi(expr) = s.kind {
464             if let hir::ExprKind::Path(_) = expr.kind {
465                 let ty = cx.typeck_results().expr_ty(expr);
466                 if ty.needs_drop(cx.tcx, cx.param_env) {
467                     let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span)
468                     {
469                         PathStatementDropSub::Suggestion { span: s.span, snippet }
470                     } else {
471                         PathStatementDropSub::Help { span: s.span }
472                     };
473                     cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
474                 } else {
475                     cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
476                 }
477             }
478         }
479     }
480 }
481
482 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
483 enum UnusedDelimsCtx {
484     FunctionArg,
485     MethodArg,
486     AssignedValue,
487     AssignedValueLetElse,
488     IfCond,
489     WhileCond,
490     ForIterExpr,
491     MatchScrutineeExpr,
492     ReturnValue,
493     BlockRetValue,
494     LetScrutineeExpr,
495     ArrayLenExpr,
496     AnonConst,
497     MatchArmExpr,
498     IndexExpr,
499 }
500
501 impl From<UnusedDelimsCtx> for &'static str {
502     fn from(ctx: UnusedDelimsCtx) -> &'static str {
503         match ctx {
504             UnusedDelimsCtx::FunctionArg => "function argument",
505             UnusedDelimsCtx::MethodArg => "method argument",
506             UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
507                 "assigned value"
508             }
509             UnusedDelimsCtx::IfCond => "`if` condition",
510             UnusedDelimsCtx::WhileCond => "`while` condition",
511             UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
512             UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
513             UnusedDelimsCtx::ReturnValue => "`return` value",
514             UnusedDelimsCtx::BlockRetValue => "block return value",
515             UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
516             UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
517             UnusedDelimsCtx::MatchArmExpr => "match arm expression",
518             UnusedDelimsCtx::IndexExpr => "index expression",
519         }
520     }
521 }
522
523 /// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
524 trait UnusedDelimLint {
525     const DELIM_STR: &'static str;
526
527     /// Due to `ref` pattern, there can be a difference between using
528     /// `{ expr }` and `expr` in pattern-matching contexts. This means
529     /// that we should only lint `unused_parens` and not `unused_braces`
530     /// in this case.
531     ///
532     /// ```rust
533     /// let mut a = 7;
534     /// let ref b = { a }; // We actually borrow a copy of `a` here.
535     /// a += 1; // By mutating `a` we invalidate any borrows of `a`.
536     /// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
537     /// ```
538     const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;
539
540     // this cannot be a constant is it refers to a static.
541     fn lint(&self) -> &'static Lint;
542
543     fn check_unused_delims_expr(
544         &self,
545         cx: &EarlyContext<'_>,
546         value: &ast::Expr,
547         ctx: UnusedDelimsCtx,
548         followed_by_block: bool,
549         left_pos: Option<BytePos>,
550         right_pos: Option<BytePos>,
551     );
552
553     fn is_expr_delims_necessary(
554         inner: &ast::Expr,
555         followed_by_block: bool,
556         followed_by_else: bool,
557     ) -> bool {
558         if followed_by_else {
559             match inner.kind {
560                 ast::ExprKind::Binary(op, ..) if op.node.lazy() => return true,
561                 _ if classify::expr_trailing_brace(inner).is_some() => return true,
562                 _ => {}
563             }
564         }
565
566         // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
567         let lhs_needs_parens = {
568             let mut innermost = inner;
569             loop {
570                 innermost = match &innermost.kind {
571                     ExprKind::Binary(_, lhs, _rhs) => lhs,
572                     ExprKind::Call(fn_, _params) => fn_,
573                     ExprKind::Cast(expr, _ty) => expr,
574                     ExprKind::Type(expr, _ty) => expr,
575                     ExprKind::Index(base, _subscript) => base,
576                     _ => break false,
577                 };
578                 if !classify::expr_requires_semi_to_be_stmt(innermost) {
579                     break true;
580                 }
581             }
582         };
583
584         lhs_needs_parens
585             || (followed_by_block
586                 && match &inner.kind {
587                     ExprKind::Ret(_)
588                     | ExprKind::Break(..)
589                     | ExprKind::Yield(..)
590                     | ExprKind::Yeet(..) => true,
591                     ExprKind::Range(_lhs, Some(rhs), _limits) => {
592                         matches!(rhs.kind, ExprKind::Block(..))
593                     }
594                     _ => parser::contains_exterior_struct_lit(&inner),
595                 })
596     }
597
598     fn emit_unused_delims_expr(
599         &self,
600         cx: &EarlyContext<'_>,
601         value: &ast::Expr,
602         ctx: UnusedDelimsCtx,
603         left_pos: Option<BytePos>,
604         right_pos: Option<BytePos>,
605     ) {
606         // If `value` has `ExprKind::Err`, unused delim lint can be broken.
607         // For example, the following code caused ICE.
608         // This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
609         // and this leads to wrong spans. #104897
610         //
611         // ```
612         // fn f(){(print!(á
613         // ```
614         use rustc_ast::visit::{walk_expr, Visitor};
615         struct ErrExprVisitor {
616             has_error: bool,
617         }
618         impl<'ast> Visitor<'ast> for ErrExprVisitor {
619             fn visit_expr(&mut self, expr: &'ast ast::Expr) {
620                 if let ExprKind::Err = expr.kind {
621                     self.has_error = true;
622                     return;
623                 }
624                 walk_expr(self, expr)
625             }
626         }
627         let mut visitor = ErrExprVisitor { has_error: false };
628         visitor.visit_expr(value);
629         if visitor.has_error {
630             return;
631         }
632         let spans = match value.kind {
633             ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
634                 if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
635                     Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
636                 } else {
637                     None
638                 }
639             }
640             ast::ExprKind::Paren(ref expr) => {
641                 let expr_span = expr.span.find_ancestor_inside(value.span);
642                 if let Some(expr_span) = expr_span {
643                     Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
644                 } else {
645                     None
646                 }
647             }
648             _ => return,
649         };
650         let keep_space = (
651             left_pos.map_or(false, |s| s >= value.span.lo()),
652             right_pos.map_or(false, |s| s <= value.span.hi()),
653         );
654         self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
655     }
656
657     fn emit_unused_delims(
658         &self,
659         cx: &EarlyContext<'_>,
660         value_span: Span,
661         spans: Option<(Span, Span)>,
662         msg: &str,
663         keep_space: (bool, bool),
664     ) {
665         let primary_span = if let Some((lo, hi)) = spans {
666             if hi.is_empty() {
667                 // do not point at delims that do not exist
668                 return;
669             }
670             MultiSpan::from(vec![lo, hi])
671         } else {
672             MultiSpan::from(value_span)
673         };
674         let suggestion = spans.map(|(lo, hi)| {
675             let sm = cx.sess().source_map();
676             let lo_replace =
677                     if keep_space.0 &&
678                         let Ok(snip) = sm.span_to_prev_source(lo) && !snip.ends_with(' ') {
679                         " "
680                         } else {
681                             ""
682                         };
683
684             let hi_replace =
685                     if keep_space.1 &&
686                         let Ok(snip) = sm.span_to_next_source(hi) && !snip.starts_with(' ') {
687                         " "
688                         } else {
689                             ""
690                         };
691             UnusedDelimSuggestion {
692                 start_span: lo,
693                 start_replace: lo_replace,
694                 end_span: hi,
695                 end_replace: hi_replace,
696             }
697         });
698         cx.emit_spanned_lint(
699             self.lint(),
700             primary_span,
701             UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
702         );
703     }
704
705     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
706         use rustc_ast::ExprKind::*;
707         let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
708             // Do not lint `unused_braces` in `if let` expressions.
709             If(ref cond, ref block, _)
710                 if !matches!(cond.kind, Let(_, _, _))
711                     || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
712             {
713                 let left = e.span.lo() + rustc_span::BytePos(2);
714                 let right = block.span.lo();
715                 (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
716             }
717
718             // Do not lint `unused_braces` in `while let` expressions.
719             While(ref cond, ref block, ..)
720                 if !matches!(cond.kind, Let(_, _, _))
721                     || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
722             {
723                 let left = e.span.lo() + rustc_span::BytePos(5);
724                 let right = block.span.lo();
725                 (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right))
726             }
727
728             ForLoop(_, ref cond, ref block, ..) => {
729                 (cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
730             }
731
732             Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
733                 let left = e.span.lo() + rustc_span::BytePos(5);
734                 (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
735             }
736
737             Ret(Some(ref value)) => {
738                 let left = e.span.lo() + rustc_span::BytePos(3);
739                 (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
740             }
741
742             Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
743
744             Assign(_, ref value, _) | AssignOp(.., ref value) => {
745                 (value, UnusedDelimsCtx::AssignedValue, false, None, None)
746             }
747             // either function/method call, or something this lint doesn't care about
748             ref call_or_other => {
749                 let (args_to_check, ctx) = match *call_or_other {
750                     Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
751                     MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
752                     // actual catch-all arm
753                     _ => {
754                         return;
755                     }
756                 };
757                 // Don't lint if this is a nested macro expansion: otherwise, the lint could
758                 // trigger in situations that macro authors shouldn't have to care about, e.g.,
759                 // when a parenthesized token tree matched in one macro expansion is matched as
760                 // an expression in another and used as a fn/method argument (Issue #47775)
761                 if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
762                     return;
763                 }
764                 for arg in args_to_check {
765                     self.check_unused_delims_expr(cx, arg, ctx, false, None, None);
766                 }
767                 return;
768             }
769         };
770         self.check_unused_delims_expr(cx, &value, ctx, followed_by_block, left_pos, right_pos);
771     }
772
773     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
774         match s.kind {
775             StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
776                 if let Some((init, els)) = local.kind.init_else_opt() {
777                     let ctx = match els {
778                         None => UnusedDelimsCtx::AssignedValue,
779                         Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
780                     };
781                     self.check_unused_delims_expr(cx, init, ctx, false, None, None);
782                 }
783             }
784             StmtKind::Expr(ref expr) => {
785                 self.check_unused_delims_expr(
786                     cx,
787                     &expr,
788                     UnusedDelimsCtx::BlockRetValue,
789                     false,
790                     None,
791                     None,
792                 );
793             }
794             _ => {}
795         }
796     }
797
798     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
799         use ast::ItemKind::*;
800
801         if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
802             self.check_unused_delims_expr(
803                 cx,
804                 expr,
805                 UnusedDelimsCtx::AssignedValue,
806                 false,
807                 None,
808                 None,
809             );
810         }
811     }
812 }
813
814 declare_lint! {
815     /// The `unused_parens` lint detects `if`, `match`, `while` and `return`
816     /// with parentheses; they do not need them.
817     ///
818     /// ### Examples
819     ///
820     /// ```rust
821     /// if(true) {}
822     /// ```
823     ///
824     /// {{produces}}
825     ///
826     /// ### Explanation
827     ///
828     /// The parentheses are not needed, and should be removed. This is the
829     /// preferred style for writing these expressions.
830     pub(super) UNUSED_PARENS,
831     Warn,
832     "`if`, `match`, `while` and `return` do not need parentheses"
833 }
834
835 pub struct UnusedParens {
836     with_self_ty_parens: bool,
837 }
838
839 impl UnusedParens {
840     pub fn new() -> Self {
841         Self { with_self_ty_parens: false }
842     }
843 }
844
845 impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
846
847 impl UnusedDelimLint for UnusedParens {
848     const DELIM_STR: &'static str = "parentheses";
849
850     const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;
851
852     fn lint(&self) -> &'static Lint {
853         UNUSED_PARENS
854     }
855
856     fn check_unused_delims_expr(
857         &self,
858         cx: &EarlyContext<'_>,
859         value: &ast::Expr,
860         ctx: UnusedDelimsCtx,
861         followed_by_block: bool,
862         left_pos: Option<BytePos>,
863         right_pos: Option<BytePos>,
864     ) {
865         match value.kind {
866             ast::ExprKind::Paren(ref inner) => {
867                 let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
868                 if !Self::is_expr_delims_necessary(inner, followed_by_block, followed_by_else)
869                     && value.attrs.is_empty()
870                     && !value.span.from_expansion()
871                     && (ctx != UnusedDelimsCtx::LetScrutineeExpr
872                         || !matches!(inner.kind, ast::ExprKind::Binary(
873                                 rustc_span::source_map::Spanned { node, .. },
874                                 _,
875                                 _,
876                             ) if node.lazy()))
877                 {
878                     self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
879                 }
880             }
881             ast::ExprKind::Let(_, ref expr, _) => {
882                 self.check_unused_delims_expr(
883                     cx,
884                     expr,
885                     UnusedDelimsCtx::LetScrutineeExpr,
886                     followed_by_block,
887                     None,
888                     None,
889                 );
890             }
891             _ => {}
892         }
893     }
894 }
895
896 impl UnusedParens {
897     fn check_unused_parens_pat(
898         &self,
899         cx: &EarlyContext<'_>,
900         value: &ast::Pat,
901         avoid_or: bool,
902         avoid_mut: bool,
903         keep_space: (bool, bool),
904     ) {
905         use ast::{BindingAnnotation, PatKind};
906
907         if let PatKind::Paren(inner) = &value.kind {
908             match inner.kind {
909                 // The lint visitor will visit each subpattern of `p`. We do not want to lint
910                 // any range pattern no matter where it occurs in the pattern. For something like
911                 // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
912                 // that if there are unnecessary parens they serve a purpose of readability.
913                 PatKind::Range(..) => return,
914                 // Avoid `p0 | .. | pn` if we should.
915                 PatKind::Or(..) if avoid_or => return,
916                 // Avoid `mut x` and `mut x @ p` if we should:
917                 PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
918                     return;
919                 }
920                 // Otherwise proceed with linting.
921                 _ => {}
922             }
923             let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
924                 Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
925             } else {
926                 None
927             };
928             self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
929         }
930     }
931 }
932
933 impl EarlyLintPass for UnusedParens {
934     #[inline]
935     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
936         match e.kind {
937             ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
938                 self.check_unused_parens_pat(cx, pat, false, false, (true, true));
939             }
940             // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
941             // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
942             // want to complain about things like `if let 42 = (42)`.
943             ExprKind::If(ref cond, ref block, ref else_)
944                 if matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
945             {
946                 self.check_unused_delims_expr(
947                     cx,
948                     cond.peel_parens(),
949                     UnusedDelimsCtx::LetScrutineeExpr,
950                     true,
951                     None,
952                     None,
953                 );
954                 for stmt in &block.stmts {
955                     <Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
956                 }
957                 if let Some(e) = else_ {
958                     <Self as UnusedDelimLint>::check_expr(self, cx, e);
959                 }
960                 return;
961             }
962             ExprKind::Match(ref _expr, ref arm) => {
963                 for a in arm {
964                     self.check_unused_delims_expr(
965                         cx,
966                         &a.body,
967                         UnusedDelimsCtx::MatchArmExpr,
968                         false,
969                         None,
970                         None,
971                     );
972                 }
973             }
974             _ => {}
975         }
976
977         <Self as UnusedDelimLint>::check_expr(self, cx, e)
978     }
979
980     fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
981         use ast::{Mutability, PatKind::*};
982         let keep_space = (false, false);
983         match &p.kind {
984             // Do not lint on `(..)` as that will result in the other arms being useless.
985             Paren(_)
986             // The other cases do not contain sub-patterns.
987             | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
988             // These are list-like patterns; parens can always be removed.
989             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
990                 self.check_unused_parens_pat(cx, p, false, false, keep_space);
991             },
992             Struct(_, _, fps, _) => for f in fps {
993                 self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
994             },
995             // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
996             Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
997             // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
998             // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
999             Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
1000         }
1001     }
1002
1003     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1004         if let StmtKind::Local(ref local) = s.kind {
1005             self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
1006         }
1007
1008         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1009     }
1010
1011     fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
1012         self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
1013     }
1014
1015     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
1016         self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
1017     }
1018
1019     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1020         match &ty.kind {
1021             ast::TyKind::Array(_, len) => {
1022                 self.check_unused_delims_expr(
1023                     cx,
1024                     &len.value,
1025                     UnusedDelimsCtx::ArrayLenExpr,
1026                     false,
1027                     None,
1028                     None,
1029                 );
1030             }
1031             ast::TyKind::Paren(r) => {
1032                 match &r.kind {
1033                     ast::TyKind::TraitObject(..) => {}
1034                     ast::TyKind::BareFn(b)
1035                         if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
1036                     ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
1037                     _ => {
1038                         let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
1039                             Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
1040                         } else {
1041                             None
1042                         };
1043                         self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
1044                     }
1045                 }
1046                 self.with_self_ty_parens = false;
1047             }
1048             _ => {}
1049         }
1050     }
1051
1052     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1053         <Self as UnusedDelimLint>::check_item(self, cx, item)
1054     }
1055
1056     fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
1057         use rustc_ast::{WhereBoundPredicate, WherePredicate};
1058         if let WherePredicate::BoundPredicate(WhereBoundPredicate {
1059                 bounded_ty,
1060                 bound_generic_params,
1061                 ..
1062             }) = pred &&
1063             let ast::TyKind::Paren(_) = &bounded_ty.kind &&
1064             bound_generic_params.is_empty() {
1065                 self.with_self_ty_parens = true;
1066         }
1067     }
1068
1069     fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
1070         assert!(!self.with_self_ty_parens);
1071     }
1072 }
1073
1074 declare_lint! {
1075     /// The `unused_braces` lint detects unnecessary braces around an
1076     /// expression.
1077     ///
1078     /// ### Example
1079     ///
1080     /// ```rust
1081     /// if { true } {
1082     ///     // ...
1083     /// }
1084     /// ```
1085     ///
1086     /// {{produces}}
1087     ///
1088     /// ### Explanation
1089     ///
1090     /// The braces are not needed, and should be removed. This is the
1091     /// preferred style for writing these expressions.
1092     pub(super) UNUSED_BRACES,
1093     Warn,
1094     "unnecessary braces around an expression"
1095 }
1096
1097 declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
1098
1099 impl UnusedDelimLint for UnusedBraces {
1100     const DELIM_STR: &'static str = "braces";
1101
1102     const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;
1103
1104     fn lint(&self) -> &'static Lint {
1105         UNUSED_BRACES
1106     }
1107
1108     fn check_unused_delims_expr(
1109         &self,
1110         cx: &EarlyContext<'_>,
1111         value: &ast::Expr,
1112         ctx: UnusedDelimsCtx,
1113         followed_by_block: bool,
1114         left_pos: Option<BytePos>,
1115         right_pos: Option<BytePos>,
1116     ) {
1117         match value.kind {
1118             ast::ExprKind::Block(ref inner, None)
1119                 if inner.rules == ast::BlockCheckMode::Default =>
1120             {
1121                 // emit a warning under the following conditions:
1122                 //
1123                 // - the block does not have a label
1124                 // - the block is not `unsafe`
1125                 // - the block contains exactly one expression (do not lint `{ expr; }`)
1126                 // - `followed_by_block` is true and the internal expr may contain a `{`
1127                 // - the block is not multiline (do not lint multiline match arms)
1128                 //      ```
1129                 //      match expr {
1130                 //          Pattern => {
1131                 //              somewhat_long_expression
1132                 //          }
1133                 //          // ...
1134                 //      }
1135                 //      ```
1136                 // - the block has no attribute and was not created inside a macro
1137                 // - if the block is an `anon_const`, the inner expr must be a literal
1138                 //   not created by a macro, i.e. do not lint on:
1139                 //      ```
1140                 //      struct A<const N: usize>;
1141                 //      let _: A<{ 2 + 3 }>;
1142                 //      let _: A<{produces_literal!()}>;
1143                 //      ```
1144                 // FIXME(const_generics): handle paths when #67075 is fixed.
1145                 if let [stmt] = inner.stmts.as_slice() {
1146                     if let ast::StmtKind::Expr(ref expr) = stmt.kind {
1147                         if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
1148                             && (ctx != UnusedDelimsCtx::AnonConst
1149                                 || (matches!(expr.kind, ast::ExprKind::Lit(_))
1150                                     && !expr.span.from_expansion()))
1151                             && !cx.sess().source_map().is_multiline(value.span)
1152                             && value.attrs.is_empty()
1153                             && !value.span.from_expansion()
1154                             && !inner.span.from_expansion()
1155                         {
1156                             self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
1157                         }
1158                     }
1159                 }
1160             }
1161             ast::ExprKind::Let(_, ref expr, _) => {
1162                 self.check_unused_delims_expr(
1163                     cx,
1164                     expr,
1165                     UnusedDelimsCtx::LetScrutineeExpr,
1166                     followed_by_block,
1167                     None,
1168                     None,
1169                 );
1170             }
1171             _ => {}
1172         }
1173     }
1174 }
1175
1176 impl EarlyLintPass for UnusedBraces {
1177     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1178         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1179     }
1180
1181     #[inline]
1182     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1183         <Self as UnusedDelimLint>::check_expr(self, cx, e);
1184
1185         if let ExprKind::Repeat(_, ref anon_const) = e.kind {
1186             self.check_unused_delims_expr(
1187                 cx,
1188                 &anon_const.value,
1189                 UnusedDelimsCtx::AnonConst,
1190                 false,
1191                 None,
1192                 None,
1193             );
1194         }
1195     }
1196
1197     fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
1198         if let ast::GenericArg::Const(ct) = arg {
1199             self.check_unused_delims_expr(
1200                 cx,
1201                 &ct.value,
1202                 UnusedDelimsCtx::AnonConst,
1203                 false,
1204                 None,
1205                 None,
1206             );
1207         }
1208     }
1209
1210     fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
1211         if let Some(anon_const) = &v.disr_expr {
1212             self.check_unused_delims_expr(
1213                 cx,
1214                 &anon_const.value,
1215                 UnusedDelimsCtx::AnonConst,
1216                 false,
1217                 None,
1218                 None,
1219             );
1220         }
1221     }
1222
1223     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1224         match ty.kind {
1225             ast::TyKind::Array(_, ref len) => {
1226                 self.check_unused_delims_expr(
1227                     cx,
1228                     &len.value,
1229                     UnusedDelimsCtx::ArrayLenExpr,
1230                     false,
1231                     None,
1232                     None,
1233                 );
1234             }
1235
1236             ast::TyKind::Typeof(ref anon_const) => {
1237                 self.check_unused_delims_expr(
1238                     cx,
1239                     &anon_const.value,
1240                     UnusedDelimsCtx::AnonConst,
1241                     false,
1242                     None,
1243                     None,
1244                 );
1245             }
1246
1247             _ => {}
1248         }
1249     }
1250
1251     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1252         <Self as UnusedDelimLint>::check_item(self, cx, item)
1253     }
1254 }
1255
1256 declare_lint! {
1257     /// The `unused_import_braces` lint catches unnecessary braces around an
1258     /// imported item.
1259     ///
1260     /// ### Example
1261     ///
1262     /// ```rust,compile_fail
1263     /// #![deny(unused_import_braces)]
1264     /// use test::{A};
1265     ///
1266     /// pub mod test {
1267     ///     pub struct A;
1268     /// }
1269     /// # fn main() {}
1270     /// ```
1271     ///
1272     /// {{produces}}
1273     ///
1274     /// ### Explanation
1275     ///
1276     /// If there is only a single item, then remove the braces (`use test::A;`
1277     /// for example).
1278     ///
1279     /// This lint is "allow" by default because it is only enforcing a
1280     /// stylistic choice.
1281     UNUSED_IMPORT_BRACES,
1282     Allow,
1283     "unnecessary braces around an imported item"
1284 }
1285
1286 declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
1287
1288 impl UnusedImportBraces {
1289     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
1290         if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
1291             // Recursively check nested UseTrees
1292             for (tree, _) in items {
1293                 self.check_use_tree(cx, tree, item);
1294             }
1295
1296             // Trigger the lint only if there is one nested item
1297             if items.len() != 1 {
1298                 return;
1299             }
1300
1301             // Trigger the lint if the nested item is a non-self single item
1302             let node_name = match items[0].0.kind {
1303                 ast::UseTreeKind::Simple(rename) => {
1304                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
1305                     if orig_ident.name == kw::SelfLower {
1306                         return;
1307                     }
1308                     rename.unwrap_or(orig_ident).name
1309                 }
1310                 ast::UseTreeKind::Glob => Symbol::intern("*"),
1311                 ast::UseTreeKind::Nested(_) => return,
1312             };
1313
1314             cx.emit_spanned_lint(
1315                 UNUSED_IMPORT_BRACES,
1316                 item.span,
1317                 UnusedImportBracesDiag { node: node_name },
1318             );
1319         }
1320     }
1321 }
1322
1323 impl EarlyLintPass for UnusedImportBraces {
1324     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1325         if let ast::ItemKind::Use(ref use_tree) = item.kind {
1326             self.check_use_tree(cx, use_tree, item);
1327         }
1328     }
1329 }
1330
1331 declare_lint! {
1332     /// The `unused_allocation` lint detects unnecessary allocations that can
1333     /// be eliminated.
1334     ///
1335     /// ### Example
1336     ///
1337     /// ```rust
1338     /// #![feature(box_syntax)]
1339     /// fn main() {
1340     ///     let a = (box [1, 2, 3]).len();
1341     /// }
1342     /// ```
1343     ///
1344     /// {{produces}}
1345     ///
1346     /// ### Explanation
1347     ///
1348     /// When a `box` expression is immediately coerced to a reference, then
1349     /// the allocation is unnecessary, and a reference (using `&` or `&mut`)
1350     /// should be used instead to avoid the allocation.
1351     pub(super) UNUSED_ALLOCATION,
1352     Warn,
1353     "detects unnecessary allocations that can be eliminated"
1354 }
1355
1356 declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
1357
1358 impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
1359     fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
1360         match e.kind {
1361             hir::ExprKind::Box(_) => {}
1362             _ => return,
1363         }
1364
1365         for adj in cx.typeck_results().expr_adjustments(e) {
1366             if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
1367                 match m {
1368                     adjustment::AutoBorrowMutability::Not => {
1369                         cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
1370                     }
1371                     adjustment::AutoBorrowMutability::Mut { .. } => {
1372                         cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
1373                     }
1374                 };
1375             }
1376         }
1377     }
1378 }