]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/unused.rs
Rollup merge of #107544 - nnethercote:improve-TokenCursor, r=petrochenkov
[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             MultiSpan::from(vec![lo, hi])
667         } else {
668             MultiSpan::from(value_span)
669         };
670         let suggestion = spans.map(|(lo, hi)| {
671             let sm = cx.sess().source_map();
672             let lo_replace =
673                     if keep_space.0 &&
674                         let Ok(snip) = sm.span_to_prev_source(lo) && !snip.ends_with(' ') {
675                         " "
676                         } else {
677                             ""
678                         };
679
680             let hi_replace =
681                     if keep_space.1 &&
682                         let Ok(snip) = sm.span_to_next_source(hi) && !snip.starts_with(' ') {
683                         " "
684                         } else {
685                             ""
686                         };
687             UnusedDelimSuggestion {
688                 start_span: lo,
689                 start_replace: lo_replace,
690                 end_span: hi,
691                 end_replace: hi_replace,
692             }
693         });
694         cx.emit_spanned_lint(
695             self.lint(),
696             primary_span,
697             UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
698         );
699     }
700
701     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
702         use rustc_ast::ExprKind::*;
703         let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
704             // Do not lint `unused_braces` in `if let` expressions.
705             If(ref cond, ref block, _)
706                 if !matches!(cond.kind, Let(_, _, _))
707                     || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
708             {
709                 let left = e.span.lo() + rustc_span::BytePos(2);
710                 let right = block.span.lo();
711                 (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
712             }
713
714             // Do not lint `unused_braces` in `while let` expressions.
715             While(ref cond, ref block, ..)
716                 if !matches!(cond.kind, Let(_, _, _))
717                     || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
718             {
719                 let left = e.span.lo() + rustc_span::BytePos(5);
720                 let right = block.span.lo();
721                 (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right))
722             }
723
724             ForLoop(_, ref cond, ref block, ..) => {
725                 (cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
726             }
727
728             Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
729                 let left = e.span.lo() + rustc_span::BytePos(5);
730                 (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
731             }
732
733             Ret(Some(ref value)) => {
734                 let left = e.span.lo() + rustc_span::BytePos(3);
735                 (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
736             }
737
738             Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
739
740             Assign(_, ref value, _) | AssignOp(.., ref value) => {
741                 (value, UnusedDelimsCtx::AssignedValue, false, None, None)
742             }
743             // either function/method call, or something this lint doesn't care about
744             ref call_or_other => {
745                 let (args_to_check, ctx) = match *call_or_other {
746                     Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
747                     MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
748                     // actual catch-all arm
749                     _ => {
750                         return;
751                     }
752                 };
753                 // Don't lint if this is a nested macro expansion: otherwise, the lint could
754                 // trigger in situations that macro authors shouldn't have to care about, e.g.,
755                 // when a parenthesized token tree matched in one macro expansion is matched as
756                 // an expression in another and used as a fn/method argument (Issue #47775)
757                 if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
758                     return;
759                 }
760                 for arg in args_to_check {
761                     self.check_unused_delims_expr(cx, arg, ctx, false, None, None);
762                 }
763                 return;
764             }
765         };
766         self.check_unused_delims_expr(cx, &value, ctx, followed_by_block, left_pos, right_pos);
767     }
768
769     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
770         match s.kind {
771             StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
772                 if let Some((init, els)) = local.kind.init_else_opt() {
773                     let ctx = match els {
774                         None => UnusedDelimsCtx::AssignedValue,
775                         Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
776                     };
777                     self.check_unused_delims_expr(cx, init, ctx, false, None, None);
778                 }
779             }
780             StmtKind::Expr(ref expr) => {
781                 self.check_unused_delims_expr(
782                     cx,
783                     &expr,
784                     UnusedDelimsCtx::BlockRetValue,
785                     false,
786                     None,
787                     None,
788                 );
789             }
790             _ => {}
791         }
792     }
793
794     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
795         use ast::ItemKind::*;
796
797         if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
798             self.check_unused_delims_expr(
799                 cx,
800                 expr,
801                 UnusedDelimsCtx::AssignedValue,
802                 false,
803                 None,
804                 None,
805             );
806         }
807     }
808 }
809
810 declare_lint! {
811     /// The `unused_parens` lint detects `if`, `match`, `while` and `return`
812     /// with parentheses; they do not need them.
813     ///
814     /// ### Examples
815     ///
816     /// ```rust
817     /// if(true) {}
818     /// ```
819     ///
820     /// {{produces}}
821     ///
822     /// ### Explanation
823     ///
824     /// The parentheses are not needed, and should be removed. This is the
825     /// preferred style for writing these expressions.
826     pub(super) UNUSED_PARENS,
827     Warn,
828     "`if`, `match`, `while` and `return` do not need parentheses"
829 }
830
831 pub struct UnusedParens {
832     with_self_ty_parens: bool,
833 }
834
835 impl UnusedParens {
836     pub fn new() -> Self {
837         Self { with_self_ty_parens: false }
838     }
839 }
840
841 impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
842
843 impl UnusedDelimLint for UnusedParens {
844     const DELIM_STR: &'static str = "parentheses";
845
846     const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;
847
848     fn lint(&self) -> &'static Lint {
849         UNUSED_PARENS
850     }
851
852     fn check_unused_delims_expr(
853         &self,
854         cx: &EarlyContext<'_>,
855         value: &ast::Expr,
856         ctx: UnusedDelimsCtx,
857         followed_by_block: bool,
858         left_pos: Option<BytePos>,
859         right_pos: Option<BytePos>,
860     ) {
861         match value.kind {
862             ast::ExprKind::Paren(ref inner) => {
863                 let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
864                 if !Self::is_expr_delims_necessary(inner, followed_by_block, followed_by_else)
865                     && value.attrs.is_empty()
866                     && !value.span.from_expansion()
867                     && (ctx != UnusedDelimsCtx::LetScrutineeExpr
868                         || !matches!(inner.kind, ast::ExprKind::Binary(
869                                 rustc_span::source_map::Spanned { node, .. },
870                                 _,
871                                 _,
872                             ) if node.lazy()))
873                 {
874                     self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
875                 }
876             }
877             ast::ExprKind::Let(_, ref expr, _) => {
878                 self.check_unused_delims_expr(
879                     cx,
880                     expr,
881                     UnusedDelimsCtx::LetScrutineeExpr,
882                     followed_by_block,
883                     None,
884                     None,
885                 );
886             }
887             _ => {}
888         }
889     }
890 }
891
892 impl UnusedParens {
893     fn check_unused_parens_pat(
894         &self,
895         cx: &EarlyContext<'_>,
896         value: &ast::Pat,
897         avoid_or: bool,
898         avoid_mut: bool,
899         keep_space: (bool, bool),
900     ) {
901         use ast::{BindingAnnotation, PatKind};
902
903         if let PatKind::Paren(inner) = &value.kind {
904             match inner.kind {
905                 // The lint visitor will visit each subpattern of `p`. We do not want to lint
906                 // any range pattern no matter where it occurs in the pattern. For something like
907                 // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
908                 // that if there are unnecessary parens they serve a purpose of readability.
909                 PatKind::Range(..) => return,
910                 // Avoid `p0 | .. | pn` if we should.
911                 PatKind::Or(..) if avoid_or => return,
912                 // Avoid `mut x` and `mut x @ p` if we should:
913                 PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
914                     return;
915                 }
916                 // Otherwise proceed with linting.
917                 _ => {}
918             }
919             let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
920                 Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
921             } else {
922                 None
923             };
924             self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
925         }
926     }
927 }
928
929 impl EarlyLintPass for UnusedParens {
930     #[inline]
931     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
932         match e.kind {
933             ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
934                 self.check_unused_parens_pat(cx, pat, false, false, (true, true));
935             }
936             // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
937             // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
938             // want to complain about things like `if let 42 = (42)`.
939             ExprKind::If(ref cond, ref block, ref else_)
940                 if matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
941             {
942                 self.check_unused_delims_expr(
943                     cx,
944                     cond.peel_parens(),
945                     UnusedDelimsCtx::LetScrutineeExpr,
946                     true,
947                     None,
948                     None,
949                 );
950                 for stmt in &block.stmts {
951                     <Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
952                 }
953                 if let Some(e) = else_ {
954                     <Self as UnusedDelimLint>::check_expr(self, cx, e);
955                 }
956                 return;
957             }
958             ExprKind::Match(ref _expr, ref arm) => {
959                 for a in arm {
960                     self.check_unused_delims_expr(
961                         cx,
962                         &a.body,
963                         UnusedDelimsCtx::MatchArmExpr,
964                         false,
965                         None,
966                         None,
967                     );
968                 }
969             }
970             _ => {}
971         }
972
973         <Self as UnusedDelimLint>::check_expr(self, cx, e)
974     }
975
976     fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
977         use ast::{Mutability, PatKind::*};
978         let keep_space = (false, false);
979         match &p.kind {
980             // Do not lint on `(..)` as that will result in the other arms being useless.
981             Paren(_)
982             // The other cases do not contain sub-patterns.
983             | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
984             // These are list-like patterns; parens can always be removed.
985             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
986                 self.check_unused_parens_pat(cx, p, false, false, keep_space);
987             },
988             Struct(_, _, fps, _) => for f in fps {
989                 self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
990             },
991             // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
992             Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
993             // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
994             // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
995             Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
996         }
997     }
998
999     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1000         if let StmtKind::Local(ref local) = s.kind {
1001             self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
1002         }
1003
1004         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1005     }
1006
1007     fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
1008         self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
1009     }
1010
1011     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
1012         self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
1013     }
1014
1015     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1016         match &ty.kind {
1017             ast::TyKind::Array(_, len) => {
1018                 self.check_unused_delims_expr(
1019                     cx,
1020                     &len.value,
1021                     UnusedDelimsCtx::ArrayLenExpr,
1022                     false,
1023                     None,
1024                     None,
1025                 );
1026             }
1027             ast::TyKind::Paren(r) => {
1028                 match &r.kind {
1029                     ast::TyKind::TraitObject(..) => {}
1030                     ast::TyKind::BareFn(b)
1031                         if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
1032                     ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
1033                     _ => {
1034                         let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
1035                             Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
1036                         } else {
1037                             None
1038                         };
1039                         self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
1040                     }
1041                 }
1042                 self.with_self_ty_parens = false;
1043             }
1044             _ => {}
1045         }
1046     }
1047
1048     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1049         <Self as UnusedDelimLint>::check_item(self, cx, item)
1050     }
1051
1052     fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
1053         use rustc_ast::{WhereBoundPredicate, WherePredicate};
1054         if let WherePredicate::BoundPredicate(WhereBoundPredicate {
1055                 bounded_ty,
1056                 bound_generic_params,
1057                 ..
1058             }) = pred &&
1059             let ast::TyKind::Paren(_) = &bounded_ty.kind &&
1060             bound_generic_params.is_empty() {
1061                 self.with_self_ty_parens = true;
1062         }
1063     }
1064
1065     fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
1066         assert!(!self.with_self_ty_parens);
1067     }
1068 }
1069
1070 declare_lint! {
1071     /// The `unused_braces` lint detects unnecessary braces around an
1072     /// expression.
1073     ///
1074     /// ### Example
1075     ///
1076     /// ```rust
1077     /// if { true } {
1078     ///     // ...
1079     /// }
1080     /// ```
1081     ///
1082     /// {{produces}}
1083     ///
1084     /// ### Explanation
1085     ///
1086     /// The braces are not needed, and should be removed. This is the
1087     /// preferred style for writing these expressions.
1088     pub(super) UNUSED_BRACES,
1089     Warn,
1090     "unnecessary braces around an expression"
1091 }
1092
1093 declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
1094
1095 impl UnusedDelimLint for UnusedBraces {
1096     const DELIM_STR: &'static str = "braces";
1097
1098     const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;
1099
1100     fn lint(&self) -> &'static Lint {
1101         UNUSED_BRACES
1102     }
1103
1104     fn check_unused_delims_expr(
1105         &self,
1106         cx: &EarlyContext<'_>,
1107         value: &ast::Expr,
1108         ctx: UnusedDelimsCtx,
1109         followed_by_block: bool,
1110         left_pos: Option<BytePos>,
1111         right_pos: Option<BytePos>,
1112     ) {
1113         match value.kind {
1114             ast::ExprKind::Block(ref inner, None)
1115                 if inner.rules == ast::BlockCheckMode::Default =>
1116             {
1117                 // emit a warning under the following conditions:
1118                 //
1119                 // - the block does not have a label
1120                 // - the block is not `unsafe`
1121                 // - the block contains exactly one expression (do not lint `{ expr; }`)
1122                 // - `followed_by_block` is true and the internal expr may contain a `{`
1123                 // - the block is not multiline (do not lint multiline match arms)
1124                 //      ```
1125                 //      match expr {
1126                 //          Pattern => {
1127                 //              somewhat_long_expression
1128                 //          }
1129                 //          // ...
1130                 //      }
1131                 //      ```
1132                 // - the block has no attribute and was not created inside a macro
1133                 // - if the block is an `anon_const`, the inner expr must be a literal
1134                 //   not created by a macro, i.e. do not lint on:
1135                 //      ```
1136                 //      struct A<const N: usize>;
1137                 //      let _: A<{ 2 + 3 }>;
1138                 //      let _: A<{produces_literal!()}>;
1139                 //      ```
1140                 // FIXME(const_generics): handle paths when #67075 is fixed.
1141                 if let [stmt] = inner.stmts.as_slice() {
1142                     if let ast::StmtKind::Expr(ref expr) = stmt.kind {
1143                         if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
1144                             && (ctx != UnusedDelimsCtx::AnonConst
1145                                 || (matches!(expr.kind, ast::ExprKind::Lit(_))
1146                                     && !expr.span.from_expansion()))
1147                             && !cx.sess().source_map().is_multiline(value.span)
1148                             && value.attrs.is_empty()
1149                             && !value.span.from_expansion()
1150                             && !inner.span.from_expansion()
1151                         {
1152                             self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
1153                         }
1154                     }
1155                 }
1156             }
1157             ast::ExprKind::Let(_, ref expr, _) => {
1158                 self.check_unused_delims_expr(
1159                     cx,
1160                     expr,
1161                     UnusedDelimsCtx::LetScrutineeExpr,
1162                     followed_by_block,
1163                     None,
1164                     None,
1165                 );
1166             }
1167             _ => {}
1168         }
1169     }
1170 }
1171
1172 impl EarlyLintPass for UnusedBraces {
1173     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1174         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1175     }
1176
1177     #[inline]
1178     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1179         <Self as UnusedDelimLint>::check_expr(self, cx, e);
1180
1181         if let ExprKind::Repeat(_, ref anon_const) = e.kind {
1182             self.check_unused_delims_expr(
1183                 cx,
1184                 &anon_const.value,
1185                 UnusedDelimsCtx::AnonConst,
1186                 false,
1187                 None,
1188                 None,
1189             );
1190         }
1191     }
1192
1193     fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
1194         if let ast::GenericArg::Const(ct) = arg {
1195             self.check_unused_delims_expr(
1196                 cx,
1197                 &ct.value,
1198                 UnusedDelimsCtx::AnonConst,
1199                 false,
1200                 None,
1201                 None,
1202             );
1203         }
1204     }
1205
1206     fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
1207         if let Some(anon_const) = &v.disr_expr {
1208             self.check_unused_delims_expr(
1209                 cx,
1210                 &anon_const.value,
1211                 UnusedDelimsCtx::AnonConst,
1212                 false,
1213                 None,
1214                 None,
1215             );
1216         }
1217     }
1218
1219     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1220         match ty.kind {
1221             ast::TyKind::Array(_, ref len) => {
1222                 self.check_unused_delims_expr(
1223                     cx,
1224                     &len.value,
1225                     UnusedDelimsCtx::ArrayLenExpr,
1226                     false,
1227                     None,
1228                     None,
1229                 );
1230             }
1231
1232             ast::TyKind::Typeof(ref anon_const) => {
1233                 self.check_unused_delims_expr(
1234                     cx,
1235                     &anon_const.value,
1236                     UnusedDelimsCtx::AnonConst,
1237                     false,
1238                     None,
1239                     None,
1240                 );
1241             }
1242
1243             _ => {}
1244         }
1245     }
1246
1247     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1248         <Self as UnusedDelimLint>::check_item(self, cx, item)
1249     }
1250 }
1251
1252 declare_lint! {
1253     /// The `unused_import_braces` lint catches unnecessary braces around an
1254     /// imported item.
1255     ///
1256     /// ### Example
1257     ///
1258     /// ```rust,compile_fail
1259     /// #![deny(unused_import_braces)]
1260     /// use test::{A};
1261     ///
1262     /// pub mod test {
1263     ///     pub struct A;
1264     /// }
1265     /// # fn main() {}
1266     /// ```
1267     ///
1268     /// {{produces}}
1269     ///
1270     /// ### Explanation
1271     ///
1272     /// If there is only a single item, then remove the braces (`use test::A;`
1273     /// for example).
1274     ///
1275     /// This lint is "allow" by default because it is only enforcing a
1276     /// stylistic choice.
1277     UNUSED_IMPORT_BRACES,
1278     Allow,
1279     "unnecessary braces around an imported item"
1280 }
1281
1282 declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
1283
1284 impl UnusedImportBraces {
1285     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
1286         if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
1287             // Recursively check nested UseTrees
1288             for (tree, _) in items {
1289                 self.check_use_tree(cx, tree, item);
1290             }
1291
1292             // Trigger the lint only if there is one nested item
1293             if items.len() != 1 {
1294                 return;
1295             }
1296
1297             // Trigger the lint if the nested item is a non-self single item
1298             let node_name = match items[0].0.kind {
1299                 ast::UseTreeKind::Simple(rename) => {
1300                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
1301                     if orig_ident.name == kw::SelfLower {
1302                         return;
1303                     }
1304                     rename.unwrap_or(orig_ident).name
1305                 }
1306                 ast::UseTreeKind::Glob => Symbol::intern("*"),
1307                 ast::UseTreeKind::Nested(_) => return,
1308             };
1309
1310             cx.emit_spanned_lint(
1311                 UNUSED_IMPORT_BRACES,
1312                 item.span,
1313                 UnusedImportBracesDiag { node: node_name },
1314             );
1315         }
1316     }
1317 }
1318
1319 impl EarlyLintPass for UnusedImportBraces {
1320     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1321         if let ast::ItemKind::Use(ref use_tree) = item.kind {
1322             self.check_use_tree(cx, use_tree, item);
1323         }
1324     }
1325 }
1326
1327 declare_lint! {
1328     /// The `unused_allocation` lint detects unnecessary allocations that can
1329     /// be eliminated.
1330     ///
1331     /// ### Example
1332     ///
1333     /// ```rust
1334     /// #![feature(box_syntax)]
1335     /// fn main() {
1336     ///     let a = (box [1, 2, 3]).len();
1337     /// }
1338     /// ```
1339     ///
1340     /// {{produces}}
1341     ///
1342     /// ### Explanation
1343     ///
1344     /// When a `box` expression is immediately coerced to a reference, then
1345     /// the allocation is unnecessary, and a reference (using `&` or `&mut`)
1346     /// should be used instead to avoid the allocation.
1347     pub(super) UNUSED_ALLOCATION,
1348     Warn,
1349     "detects unnecessary allocations that can be eliminated"
1350 }
1351
1352 declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
1353
1354 impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
1355     fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
1356         match e.kind {
1357             hir::ExprKind::Box(_) => {}
1358             _ => return,
1359         }
1360
1361         for adj in cx.typeck_results().expr_adjustments(e) {
1362             if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
1363                 match m {
1364                     adjustment::AutoBorrowMutability::Not => {
1365                         cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
1366                     }
1367                     adjustment::AutoBorrowMutability::Mut { .. } => {
1368                         cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
1369                     }
1370                 };
1371             }
1372         }
1373     }
1374 }