]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_lint/src/unused.rs
Test drop_tracking_mir before querying generator.
[rust.git] / compiler / rustc_lint / src / unused.rs
index f2ee9ab1a19873cfac16b3e6f2c29c253a5267a5..4c9b3df2dbd33d706d04c3cc5e911ceeb9c70a2c 100644 (file)
@@ -824,7 +824,17 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
     "`if`, `match`, `while` and `return` do not need parentheses"
 }
 
-declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
+pub struct UnusedParens {
+    with_self_ty_parens: bool,
+}
+
+impl UnusedParens {
+    pub fn new() -> Self {
+        Self { with_self_ty_parens: false }
+    }
+}
+
+impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
 
 impl UnusedDelimLint for UnusedParens {
     const DELIM_STR: &'static str = "parentheses";
@@ -999,36 +1009,58 @@ fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
     }
 
     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
-        if let ast::TyKind::Paren(r) = &ty.kind {
-            match &r.kind {
-                ast::TyKind::TraitObject(..) => {}
-                ast::TyKind::BareFn(b) if b.generic_params.len() > 0 => {}
-                ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
-                ast::TyKind::Array(_, len) => {
-                    self.check_unused_delims_expr(
-                        cx,
-                        &len.value,
-                        UnusedDelimsCtx::ArrayLenExpr,
-                        false,
-                        None,
-                        None,
-                    );
-                }
-                _ => {
-                    let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
-                        Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
-                    } else {
-                        None
-                    };
-                    self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
+        match &ty.kind {
+            ast::TyKind::Array(_, len) => {
+                self.check_unused_delims_expr(
+                    cx,
+                    &len.value,
+                    UnusedDelimsCtx::ArrayLenExpr,
+                    false,
+                    None,
+                    None,
+                );
+            }
+            ast::TyKind::Paren(r) => {
+                match &r.kind {
+                    ast::TyKind::TraitObject(..) => {}
+                    ast::TyKind::BareFn(b)
+                        if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
+                    ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
+                    _ => {
+                        let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
+                            Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
+                        } else {
+                            None
+                        };
+                        self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
+                    }
                 }
+                self.with_self_ty_parens = false;
             }
+            _ => {}
         }
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
         <Self as UnusedDelimLint>::check_item(self, cx, item)
     }
+
+    fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
+        use rustc_ast::{WhereBoundPredicate, WherePredicate};
+        if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                bounded_ty,
+                bound_generic_params,
+                ..
+            }) = pred &&
+            let ast::TyKind::Paren(_) = &bounded_ty.kind &&
+            bound_generic_params.is_empty() {
+                self.with_self_ty_parens = true;
+        }
+    }
+
+    fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
+        assert!(!self.with_self_ty_parens);
+    }
 }
 
 declare_lint! {
@@ -1095,17 +1127,21 @@ fn check_unused_delims_expr(
                 //      ```
                 // - the block has no attribute and was not created inside a macro
                 // - if the block is an `anon_const`, the inner expr must be a literal
-                //      (do not lint `struct A<const N: usize>; let _: A<{ 2 + 3 }>;`)
-                //
+                //   not created by a macro, i.e. do not lint on:
+                //      ```
+                //      struct A<const N: usize>;
+                //      let _: A<{ 2 + 3 }>;
+                //      let _: A<{produces_literal!()}>;
+                //      ```
                 // FIXME(const_generics): handle paths when #67075 is fixed.
                 if let [stmt] = inner.stmts.as_slice() {
                     if let ast::StmtKind::Expr(ref expr) = stmt.kind {
                         if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
                             && (ctx != UnusedDelimsCtx::AnonConst
-                                || matches!(expr.kind, ast::ExprKind::Lit(_)))
+                                || (matches!(expr.kind, ast::ExprKind::Lit(_))
+                                    && !expr.span.from_expansion()))
                             && !cx.sess().source_map().is_multiline(value.span)
                             && value.attrs.is_empty()
-                            && !expr.span.from_expansion()
                             && !value.span.from_expansion()
                             && !inner.span.from_expansion()
                         {