]> git.lizzy.rs Git - rust.git/commitdiff
Merge remote-tracking branch 'upstream/master' into rustup
authorflip1995 <philipp.krones@embecosm.com>
Thu, 8 Apr 2021 15:18:19 +0000 (17:18 +0200)
committerflip1995 <philipp.krones@embecosm.com>
Thu, 8 Apr 2021 15:36:41 +0000 (17:36 +0200)
19 files changed:
1  2 
clippy_lints/src/default_numeric_fallback.rs
clippy_lints/src/functions/must_use.rs
clippy_lints/src/lib.rs
clippy_lints/src/literal_representation.rs
clippy_lints/src/loops/needless_range_loop.rs
clippy_lints/src/loops/never_loop.rs
clippy_lints/src/matches.rs
clippy_lints/src/missing_doc.rs
clippy_lints/src/mut_key.rs
clippy_lints/src/mut_reference.rs
clippy_lints/src/pass_by_ref_or_value.rs
clippy_lints/src/pattern_type_mismatch.rs
clippy_lints/src/unit_return_expecting_ord.rs
clippy_lints/src/unnecessary_sort_by.rs
clippy_lints/src/utils/inspector.rs
clippy_utils/src/consts.rs
clippy_utils/src/hir_utils.rs
clippy_utils/src/lib.rs
clippy_utils/src/qualify_min_const_fn.rs

index 0000000000000000000000000000000000000000,9ea8e2eaa2a79eb7aef8694bb12bf62741210289..20288427b4a74550d2594ff36e4e3d2b284bf821
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,272 +1,272 @@@
 -    } else if !attr.is_value_str() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+ use rustc_ast::ast::Attribute;
+ use rustc_errors::Applicability;
+ use rustc_hir::def_id::DefIdSet;
+ use rustc_hir::{self as hir, def::Res, intravisit, QPath};
+ use rustc_lint::{LateContext, LintContext};
+ use rustc_middle::{
+     hir::map::Map,
+     lint::in_external_macro,
+     ty::{self, Ty},
+ };
+ use rustc_span::{sym, Span};
+ use clippy_utils::attrs::is_proc_macro;
+ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
+ use clippy_utils::source::snippet_opt;
+ use clippy_utils::ty::is_must_use_ty;
+ use clippy_utils::{match_def_path, must_use_attr, return_ty, trait_ref_of_method};
+ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
+ pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+     let attrs = cx.tcx.hir().attrs(item.hir_id());
+     let attr = must_use_attr(attrs);
+     if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
+         let is_public = cx.access_levels.is_exported(item.hir_id());
+         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+         if let Some(attr) = attr {
+             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+             return;
+         } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
+             check_must_use_candidate(
+                 cx,
+                 sig.decl,
+                 cx.tcx.hir().body(*body_id),
+                 item.span,
+                 item.hir_id(),
+                 item.span.with_hi(sig.decl.output.span().hi()),
+                 "this function could have a `#[must_use]` attribute",
+             );
+         }
+     }
+ }
+ pub(super) fn check_impl_item(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
+     if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
+         let is_public = cx.access_levels.is_exported(item.hir_id());
+         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+         let attrs = cx.tcx.hir().attrs(item.hir_id());
+         let attr = must_use_attr(attrs);
+         if let Some(attr) = attr {
+             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+         } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.hir_id()).is_none() {
+             check_must_use_candidate(
+                 cx,
+                 sig.decl,
+                 cx.tcx.hir().body(*body_id),
+                 item.span,
+                 item.hir_id(),
+                 item.span.with_hi(sig.decl.output.span().hi()),
+                 "this method could have a `#[must_use]` attribute",
+             );
+         }
+     }
+ }
+ pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+     if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
+         let is_public = cx.access_levels.is_exported(item.hir_id());
+         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
+         let attrs = cx.tcx.hir().attrs(item.hir_id());
+         let attr = must_use_attr(attrs);
+         if let Some(attr) = attr {
+             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+         } else if let hir::TraitFn::Provided(eid) = *eid {
+             let body = cx.tcx.hir().body(eid);
+             if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
+                 check_must_use_candidate(
+                     cx,
+                     sig.decl,
+                     body,
+                     item.span,
+                     item.hir_id(),
+                     item.span.with_hi(sig.decl.output.span().hi()),
+                     "this method could have a `#[must_use]` attribute",
+                 );
+             }
+         }
+     }
+ }
+ fn check_needless_must_use(
+     cx: &LateContext<'_>,
+     decl: &hir::FnDecl<'_>,
+     item_id: hir::HirId,
+     item_span: Span,
+     fn_header_span: Span,
+     attr: &Attribute,
+ ) {
+     if in_external_macro(cx.sess(), item_span) {
+         return;
+     }
+     if returns_unit(decl) {
+         span_lint_and_then(
+             cx,
+             MUST_USE_UNIT,
+             fn_header_span,
+             "this unit-returning function has a `#[must_use]` attribute",
+             |diag| {
+                 diag.span_suggestion(
+                     attr.span,
+                     "remove the attribute",
+                     "".into(),
+                     Applicability::MachineApplicable,
+                 );
+             },
+         );
++    } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+         span_lint_and_help(
+             cx,
+             DOUBLE_MUST_USE,
+             fn_header_span,
+             "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`",
+             None,
+             "either add some descriptive text or remove the attribute",
+         );
+     }
+ }
+ fn check_must_use_candidate<'tcx>(
+     cx: &LateContext<'tcx>,
+     decl: &'tcx hir::FnDecl<'_>,
+     body: &'tcx hir::Body<'_>,
+     item_span: Span,
+     item_id: hir::HirId,
+     fn_span: Span,
+     msg: &str,
+ ) {
+     if has_mutable_arg(cx, body)
+         || mutates_static(cx, body)
+         || in_external_macro(cx.sess(), item_span)
+         || returns_unit(decl)
+         || !cx.access_levels.is_exported(item_id)
+         || is_must_use_ty(cx, return_ty(cx, item_id))
+     {
+         return;
+     }
+     span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
+         if let Some(snippet) = snippet_opt(cx, fn_span) {
+             diag.span_suggestion(
+                 fn_span,
+                 "add the attribute",
+                 format!("#[must_use] {}", snippet),
+                 Applicability::MachineApplicable,
+             );
+         }
+     });
+ }
+ fn returns_unit(decl: &hir::FnDecl<'_>) -> bool {
+     match decl.output {
+         hir::FnRetTy::DefaultReturn(_) => true,
+         hir::FnRetTy::Return(ty) => match ty.kind {
+             hir::TyKind::Tup(tys) => tys.is_empty(),
+             hir::TyKind::Never => true,
+             _ => false,
+         },
+     }
+ }
+ fn has_mutable_arg(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool {
+     let mut tys = DefIdSet::default();
+     body.params.iter().any(|param| is_mutable_pat(cx, param.pat, &mut tys))
+ }
+ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) -> bool {
+     if let hir::PatKind::Wild = pat.kind {
+         return false; // ignore `_` patterns
+     }
+     if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
+         is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys)
+     } else {
+         false
+     }
+ }
+ static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]];
+ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
+     match *ty.kind() {
+         // primitive types are never mutable
+         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
+         ty::Adt(adt, substs) => {
+             tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+                 || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path))
+                     && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
+         },
+         ty::Tuple(substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)),
+         ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys),
+         ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => {
+             mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys)
+         },
+         // calling something constitutes a side effect, so return true on all callables
+         // also never calls need not be used, so return true for them, too
+         _ => true,
+     }
+ }
+ struct StaticMutVisitor<'a, 'tcx> {
+     cx: &'a LateContext<'tcx>,
+     mutates_static: bool,
+ }
+ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
+     type Map = Map<'tcx>;
+     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+         use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
+         if self.mutates_static {
+             return;
+         }
+         match expr.kind {
+             Call(_, args) | MethodCall(_, _, args, _) => {
+                 let mut tys = DefIdSet::default();
+                 for arg in args {
+                     if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                         && is_mutable_ty(
+                             self.cx,
+                             self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+                             arg.span,
+                             &mut tys,
+                         )
+                         && is_mutated_static(arg)
+                     {
+                         self.mutates_static = true;
+                         return;
+                     }
+                     tys.clear();
+                 }
+             },
+             Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
+                 self.mutates_static |= is_mutated_static(target)
+             },
+             _ => {},
+         }
+     }
+     fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+         intravisit::NestedVisitorMap::None
+     }
+ }
+ fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
+     use hir::ExprKind::{Field, Index, Path};
+     match e.kind {
+         Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
+         Path(_) => true,
+         Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
+         _ => false,
+     }
+ }
+ fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
+     let mut v = StaticMutVisitor {
+         cx,
+         mutates_static: false,
+     };
+     intravisit::walk_expr(&mut v, &body.value);
+     v.mutates_static
+ }
index a99ed7656bfb3619d10f1e12b80c2b282329b409,cd92b551abd6eaeed1c38e34c6f0bad3e8992132..7abd02c53f137343718fea62d8030a74a5259f58
@@@ -4,9 -4,7 +4,8 @@@
  #![feature(box_syntax)]
  #![feature(drain_filter)]
  #![feature(in_band_lifetimes)]
 +#![feature(iter_zip)]
  #![feature(once_cell)]
- #![cfg_attr(bootstrap, feature(or_patterns))]
  #![feature(rustc_private)]
  #![feature(stmt_expr_attributes)]
  #![feature(control_flow_enum)]
Simple merge
index 2f2dc4cfc6b03eb972d95bbb573c8789897e038d,a892e24482b943a3ddeaceaf6a2873d79ca1f520..c8ee0abd3dfefa81cf6db517adbaba50ea815628
@@@ -1669,7 -1670,7 +1671,7 @@@ wher
  
      values.sort();
  
-     for (a, b) in iter::zip(&values, &values[1..]) {
 -    for (a, b) in values.iter().zip(values.iter().skip(1)) {
++    for (a, b) in iter::zip(&values, values.iter().skip(1)) {
          match (a, b) {
              (&Kind::Start(_, ra), &Kind::End(_, rb)) => {
                  if ra.node != rb.node {
index 21b4983a1af0270020f62aa12abde52f27a710e5,d731a9fe223aba88f8746c4807ea8f86f3cca8ef..dfab3e8a93112b447bed16a486dce483a2031333
@@@ -93,9 -93,9 +93,9 @@@ impl MissingDoc 
              return;
          }
  
--        let has_doc = attrs
--            .iter()
-             .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta()));
 -            .any(|a| a.is_doc_comment() || a.doc_str().is_some() || a.is_value_str() || Self::has_include(a.meta()));
++        let has_doc = attrs.iter().any(|a| {
++            a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta())
++        });
          if !has_doc {
              span_lint(
                  cx,
Simple merge
Simple merge
index c0c2ab67e382e0194906e80c4955867a84636b7c,8c198cecd6a7f2919e0e028cf3184b45e2b1a4a1..9bab783998aa5693088f8352a3319e55f23086a1
@@@ -135,8 -134,8 +135,8 @@@ impl<'tcx> LateLintPass<'tcx> for Patte
          hir_id: HirId,
      ) {
          if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) {
 -            for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) {
 +            for (param, ty) in iter::zip(body.params, fn_sig.inputs()) {
-                 apply_lint(cx, &param.pat, ty, DerefPossible::Impossible);
+                 apply_lint(cx, param.pat, ty, DerefPossible::Impossible);
              }
          }
      }
index 6becff9662a76ff79b74e191baf506b7788ee73b,03711eb5b65e8d9572453cf473eef3c570cac9ac..347d858b640264caed856933662baee8e59f7e94
@@@ -80,10 -79,10 +80,9 @@@ fn mirrored_exprs
              mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident)
          },
          // Two arrays with mirrored contents
 -        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs
 -            .iter()
 -            .zip(right_exprs.iter())
 -            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
 +        (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
-             iter::zip(*left_exprs, *right_exprs)
-                 .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-         }
++            iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
++        },
          // The two exprs are function calls.
          // Check to see that the function itself and its arguments are mirrored
          (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => {
              ExprKind::MethodCall(right_segment, _, right_args, _),
          ) => {
              left_segment.ident == right_segment.ident
 -                && left_args
 -                    .iter()
 -                    .zip(right_args.iter())
 +                && iter::zip(*left_args, *right_args)
                      .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-         }
+         },
          // Two tuples with mirrored contents
 -        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs
 -            .iter()
 -            .zip(right_exprs.iter())
 -            .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)),
 +        (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
-             iter::zip(*left_exprs, *right_exprs)
-                 .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
-         }
++            iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident))
++        },
          // Two binary ops, which are the same operation and which have mirrored arguments
          (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => {
              left_op.node == right_op.node
                  },
              )),
          ) => {
-             (iter::zip(*left_segments, *right_segments)
 -            (left_segments
 -                .iter()
 -                .zip(right_segments.iter())
--                .all(|(left, right)| left.ident == right.ident)
++            (iter::zip(*left_segments, *right_segments).all(|(left, right)| left.ident == right.ident)
                  && left_segments
                      .iter()
                      .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident))
index b3fe66ed4285eff8ba0a54f4e48275c70e0ee1ca,32d34e8d31eada4bf93cf702d57d418b5565be25..4665eeeff7b21c2264c1469d0966cad2e7c780f7
@@@ -318,10 -319,6 +318,10 @@@ fn print_expr(cx: &LateContext<'_>, exp
                              print_expr(cx, out_expr, indent + 1);
                          }
                      },
-                     }
 +                    hir::InlineAsmOperand::Const { anon_const } => {
 +                        println!("{}anon_const:", ind);
 +                        print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
++                    },
                  }
              }
          },
index 8af10ebe777ea0ed4c2c9b54df7b6017558a9355,ebe896b7ae86771c13ecabf27d3434a7d53ec6e0..2a305d8bcbe0d1682b06840d864aac361df9d93d
@@@ -140,12 -139,12 +140,10 @@@ impl Constant 
              (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
              (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
              (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
-             (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => {
-                 iter::zip(l, r)
-                     .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
-                     .find(|r| r.map_or(true, |o| o != Ordering::Equal))
-                     .unwrap_or_else(|| Some(l.len().cmp(&r.len())))
-             }
 -            (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l
 -                .iter()
 -                .zip(r.iter())
++            (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => iter::zip(l, r)
+                 .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
+                 .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+                 .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
              (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
                  match Self::partial_cmp(tcx, cmp_type, lv, rv) {
                      Some(Equal) => Some(ls.cmp(rs)),
Simple merge
index 6b235875c203157cc40b6c3ab96bdda15417d5d0,6088cd323c4b110c69e0856fb9450724b043709a..185ef296f3f2c1c755e73b9675c99dfa8c2d3681
@@@ -1,7 -1,5 +1,6 @@@
  #![feature(box_patterns)]
  #![feature(in_band_lifetimes)]
- #![cfg_attr(bootstrap, feature(or_patterns))]
 +#![feature(iter_zip)]
  #![feature(rustc_private)]
  #![recursion_limit = "512"]
  #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
index dac4d93499dc2e7c31a653a25a9673f7fc9d5d04,1391f7505e27cc3655ec67b9b8ad7661ce322c4d..b52cbf31e35aad71c4f8a31c704633e6b5dab059
@@@ -210,21 -210,21 +210,19 @@@ fn check_statement(tcx: TyCtxt<'tcx>, b
          StatementKind::Assign(box (place, rval)) => {
              check_place(tcx, *place, span, body)?;
              check_rvalue(tcx, body, def_id, rval, span)
--        }
++        },
  
 -        StatementKind::FakeRead(_, place) |
 +        StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body),
          // just an assignment
          StatementKind::SetDiscriminant { place, .. } => check_place(tcx, **place, span, body),
  
          StatementKind::LlvmInlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
  
--        StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping{
--          dst, src, count,
--        }) => {
--          check_operand(tcx, dst, span, body)?;
--          check_operand(tcx, src, span, body)?;
--          check_operand(tcx, count, span, body)
--        }
++        StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
++            check_operand(tcx, dst, span, body)?;
++            check_operand(tcx, src, span, body)?;
++            check_operand(tcx, count, span, body)
++        },
          // These are all NOPs
          StatementKind::StorageLive(_)
          | StatementKind::StorageDead(_)