diff options
| author | Philipp Krones <hello@philkrones.com> | 2024-09-24 11:58:04 +0200 |
|---|---|---|
| committer | Philipp Krones <hello@philkrones.com> | 2024-09-24 11:58:04 +0200 |
| commit | ae1c19146776bec5275c71e64f26f02ecd2893b7 (patch) | |
| tree | fd7272e3195c9c46e491eff35ed4e08a1df42058 /src/tools/clippy/clippy_utils | |
| parent | 4cadeda932d5c261a9a0b1bbd25c4486e4e0a4c6 (diff) | |
| parent | 7901289135257ca0fbed3a5522526f95b0f5edba (diff) | |
| download | rust-ae1c19146776bec5275c71e64f26f02ecd2893b7.tar.gz rust-ae1c19146776bec5275c71e64f26f02ecd2893b7.zip | |
Merge commit '7901289135257ca0fbed3a5522526f95b0f5edba' into clippy-subtree-update
Diffstat (limited to 'src/tools/clippy/clippy_utils')
22 files changed, 144 insertions, 188 deletions
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 629ce9d04d4..fe30b10c435 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.82" +version = "0.1.83" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index de8bbb619f8..49323492e12 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -242,13 +242,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { } fn eq_coroutine_kind(a: Option<CoroutineKind>, b: Option<CoroutineKind>) -> bool { - match (a, b) { + matches!( + (a, b), (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. })) - | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) - | (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. })) - | (None, None) => true, - _ => false, - } + | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) + | ( + Some(CoroutineKind::AsyncGen { .. }), + Some(CoroutineKind::AsyncGen { .. }) + ) + | (None, None) + ) } pub fn eq_field(l: &ExprField, r: &ExprField) -> bool { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs b/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs index eefcbabd835..032cd3ed739 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs @@ -1,5 +1,5 @@ use core::iter::FusedIterator; -use rustc_ast::visit::{walk_attribute, walk_expr, Visitor}; +use rustc_ast::visit::{Visitor, walk_attribute, walk_expr}; use rustc_ast::{Attribute, Expr}; use rustc_span::symbol::Ident; diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 42c8b218d14..edc9c6ccdff 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -4,7 +4,7 @@ use rustc_lexer::TokenKind; use rustc_lint::LateContext; use rustc_middle::ty::{AdtDef, TyCtxt}; use rustc_session::Session; -use rustc_span::{sym, Span}; +use rustc_span::{Span, sym}; use std::str::FromStr; use crate::source::SpanRangeExt; @@ -183,15 +183,15 @@ pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { let mut iter = tokenize_with_text(src); // Search for the token sequence [`#`, `[`, `cfg`] - while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { - let mut iter = iter.by_ref().skip_while(|(t, _)| { + while iter.any(|(t, ..)| matches!(t, TokenKind::Pound)) { + let mut iter = iter.by_ref().skip_while(|(t, ..)| { matches!( t, TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } ) }); - if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) - && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) + if matches!(iter.next(), Some((TokenKind::OpenBracket, ..))) + && matches!(iter.next(), Some((TokenKind::Ident, "cfg", _))) { return true; } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 2bd6837d973..9143d292f67 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -12,9 +12,9 @@ //! code was written, and check if the span contains that text. Note this will only work correctly //! if the span is not from a `macro_rules` based macro. +use rustc_ast::AttrStyle; use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy}; use rustc_ast::token::CommentKind; -use rustc_ast::AttrStyle; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, @@ -24,7 +24,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{Ident, kw}; use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 760d5bc95f7..bf47cf6d372 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1,24 +1,24 @@ #![allow(clippy::float_cmp)] use crate::macros::HirNode; -use crate::source::{walk_span_to_context, SpanRangeExt}; +use crate::source::{SpanRangeExt, walk_span_to_context}; use crate::{clip, is_direct_expn_of, sext, unsext}; -use rustc_apfloat::ieee::{Half, Quad}; use rustc_apfloat::Float; +use rustc_apfloat::ieee::{Half, Quad}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; -use rustc_middle::mir::interpret::{alloc_range, Scalar}; use rustc_middle::mir::ConstValue; +use rustc_middle::mir::interpret::{Scalar, alloc_range}; use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; -use rustc_span::{sym, SyntaxContext}; +use rustc_span::{SyntaxContext, sym}; use rustc_target::abi::Size; use std::cell::Cell; use std::cmp::Ordering; @@ -581,7 +581,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> { - use self::Constant::{Int, F32, F64}; + use self::Constant::{F32, F64, Int}; match *o { Int(value) => { let ty::Int(ity) = *ty.kind() else { return None }; diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index a6dd12a28c5..9420d84b959 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -14,12 +14,12 @@ use crate::ty::{all_predicates_of, is_copy}; use crate::visitors::is_const_evaluatable; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; -use rustc_span::{sym, Symbol}; +use rustc_span::{Symbol, sym}; use std::{cmp, ops}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index e09cc9edf3a..3175a9a1dd3 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -3,14 +3,14 @@ #![deny(clippy::missing_docs_in_private_items)] use crate::consts::{ConstEvalCtxt, Constant}; -use crate::ty::is_type_diagnostic_item; use crate::is_expn_of; +use crate::ty::is_type_diagnostic_item; use rustc_ast::ast; use rustc_hir as hir; use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath}; use rustc_lint::LateContext; -use rustc_span::{sym, symbol, Span}; +use rustc_span::{Span, sym, symbol}; /// The essential nodes of a desugared for loop as well as the entire span: /// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`. diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f61ef9ac1b0..76900379ac7 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1,20 +1,20 @@ use crate::consts::ConstEvalCtxt; use crate::macros::macro_backtrace; -use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt}; +use crate::source::{SpanRange, SpanRangeExt, walk_span_to_context}; use crate::tokenize_with_text; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHasher; -use rustc_hir::def::Res; use rustc_hir::MatchSource::TryDesugar; +use rustc_hir::def::Res; use rustc_hir::{ ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, }; -use rustc_lexer::{tokenize, TokenKind}; +use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::LateContext; use rustc_middle::ty::TypeckResults; -use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym}; use std::hash::{Hash, Hasher}; use std::ops::Range; @@ -1194,8 +1194,8 @@ fn eq_span_tokens( && let Some(rsrc) = right.get_source_range(cx) && let Some(rsrc) = rsrc.as_str() { - let pred = |t: &(_, _)| pred(t.0); - let map = |(_, x)| x; + let pred = |&(token, ..): &(TokenKind, _, _)| pred(token); + let map = |(_, source, _)| source; let ltok = tokenize_with_text(lsrc).filter(pred).map(map); let rtok = tokenize_with_text(rsrc).filter(pred).map(map); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 0d0d6219c5e..2fee6473910 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -78,7 +78,7 @@ pub mod visitors; pub use self::attrs::*; pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match}; pub use self::hir_utils::{ - both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash, + HirEqInterExpr, SpanlessEq, SpanlessHash, both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, }; use core::mem; @@ -94,20 +94,20 @@ use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; +use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalModDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::definitions::{DefPath, DefPathData}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; -use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; -use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ - self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, - ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, - ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, - Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, - TraitRef, TyKind, UnOp, + self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, + Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, + ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, + PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, + TyKind, UnOp, def, }; -use rustc_lexer::{tokenize, TokenKind}; +use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::Const; @@ -120,12 +120,12 @@ use rustc_middle::ty::{ }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; -use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::{sym, Span}; +use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{InnerSpan, Span, sym}; use rustc_target::abi::Integer; use visitors::Visitable; -use crate::consts::{mir_to_const, ConstEvalCtxt, Constant}; +use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; use crate::higher::Range; use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type}; use crate::visitors::for_each_expr_without_closures; @@ -263,9 +263,13 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> } } - /// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`. -pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool { +pub fn is_enum_variant_ctor( + cx: &LateContext<'_>, + enum_item: Symbol, + variant_name: Symbol, + ctor_call_id: DefId, +) -> bool { let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else { return false; }; @@ -667,6 +671,17 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re } } +/// Finds the crates called `name`, may be multiple due to multiple major versions. +pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> { + tcx.crates(()) + .iter() + .copied() + .filter(move |&num| tcx.crate_name(num) == name) + .map(CrateNum::as_def_id) + .map(|id| Res::Def(tcx.def_kind(id), id)) + .collect() +} + /// Resolves a def path like `std::vec::Vec`. /// /// Can return multiple resolutions when there are multiple versions of the same crate, e.g. @@ -677,15 +692,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re /// /// This function is expensive and should be used sparingly. pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { - fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ { - tcx.crates(()) - .iter() - .copied() - .filter(move |&num| tcx.crate_name(num) == name) - .map(CrateNum::as_def_id) - } - - let (base, mut path) = match *path { + let (base, path) = match *path { [primitive] => { return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)]; }, @@ -701,18 +708,25 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { None }; - let starts = find_primitive_impls(tcx, base) - .chain(find_crates(tcx, base_sym)) + let crates = find_primitive_impls(tcx, base) .chain(local_crate) - .map(|id| Res::Def(tcx.def_kind(id), id)); + .map(|id| Res::Def(tcx.def_kind(id), id)) + .chain(find_crates(tcx, base_sym)) + .collect(); - let mut resolutions: Vec<Res> = starts.collect(); + def_path_res_with_base(tcx, crates, path) +} +/// Resolves a def path like `vec::Vec` with the base `std`. +/// +/// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up +/// items from the same crate repeatedly, although should still be used sparingly. +pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[&str]) -> Vec<Res> { while let [segment, rest @ ..] = path { path = rest; let segment = Symbol::intern(segment); - resolutions = resolutions + base = base .into_iter() .filter_map(|res| res.opt_def_id()) .flat_map(|def_id| { @@ -731,7 +745,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { .collect(); } - resolutions + base } /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`]. @@ -2944,13 +2958,14 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU } /// Tokenizes the input while keeping the text associated with each token. -pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> { +pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> { let mut pos = 0; tokenize(s).map(move |t| { let end = pos + t.len; let range = pos as usize..end as usize; + let inner = InnerSpan::new(range.start, range.end); pos = end; - (t.kind, s.get(range).unwrap_or_default()) + (t.kind, s.get(range).unwrap_or_default(), inner) }) } @@ -2974,8 +2989,8 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool { pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String { let snippet = sm.span_to_snippet(span).unwrap_or_default(); let res = tokenize_with_text(&snippet) - .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. })) - .map(|(_, s)| s) + .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. })) + .map(|(_, s, _)| s) .join("\n"); res } @@ -2995,7 +3010,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span { /// pat: Some(a) /// else_body: return None /// ``` - +/// /// And for this example: /// ```ignore /// let Some(FooBar { a, b }) = ex else { return None }; @@ -3005,7 +3020,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span { /// pat: Some(FooBar { a, b }) /// else_body: return None /// ``` - +/// /// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because /// the question mark operator is applicable here. Callers have to check whether we are in a /// constant or not. diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index 1d7479bff82..9c4d19ac1f1 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -1,6 +1,6 @@ #![allow(clippy::similar_names)] // `expr` and `expn` -use crate::visitors::{for_each_expr_without_closures, Descend}; +use crate::visitors::{Descend, for_each_expr_without_closures}; use arrayvec::ArrayVec; use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; @@ -10,7 +10,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::LateContext; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; -use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol}; +use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym}; use std::ops::ControlFlow; const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[ diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 654fb564848..59bb5e35cda 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -2,7 +2,7 @@ use rustc_hir::{Expr, HirId}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ - traversal, BasicBlock, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK, + BasicBlock, Body, InlineAsmOperand, Local, Location, Place, START_BLOCK, StatementKind, TerminatorKind, traversal, }; use rustc_middle::ty::TyCtxt; @@ -112,14 +112,10 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool { /// Convenience wrapper around `visit_local_usage`. pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> { - visit_local_usage( - &[local], - mir, - Location { - block: START_BLOCK, - statement_index: 0, - }, - ) + visit_local_usage(&[local], mir, Location { + block: START_BLOCK, + statement_index: 0, + }) .map(|mut vec| { let LocalUsage { local_use_locs, .. } = vec.remove(0); let mut locations = local_use_locs diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index a30edc48fff..11a98b02f33 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -29,7 +29,11 @@ pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; // Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items. -// ... none currently! +pub const ABORT: [&str; 3] = ["std", "process", "abort"]; +pub const CHILD: [&str; 3] = ["std", "process", "Child"]; +pub const CHILD_ID: [&str; 4] = ["std", "process", "Child", "id"]; +pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"]; +pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; // Paths in clippy itself pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"]; diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs index 991ea428dc3..273c1b0defa 100644 --- a/src/tools/clippy/clippy_utils/src/ptr.rs +++ b/src/tools/clippy/clippy_utils/src/ptr.rs @@ -1,5 +1,5 @@ use crate::source::snippet; -use crate::visitors::{for_each_expr_without_closures, Descend}; +use crate::visitors::{Descend, for_each_expr_without_closures}; use crate::{path_to_local_id, strip_pat_refs}; use core::ops::ControlFlow; use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind}; diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index d9befb3c157..2ed20b7202c 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -18,8 +18,8 @@ use rustc_middle::mir::{ use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt}; -use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_span::symbol::sym; use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; use std::borrow::Cow; diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 482e1e0147b..4ad7575e720 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -9,10 +9,10 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource}; use rustc_lint::{EarlyContext, LateContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::source_map::{original_sp, SourceMap}; +use rustc_span::source_map::{SourceMap, original_sp}; use rustc_span::{ - hygiene, BytePos, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext, - DUMMY_SP, + BytePos, DUMMY_SP, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext, + hygiene, }; use std::borrow::Cow; use std::fmt; @@ -666,39 +666,6 @@ pub fn walk_span_to_context(span: Span, outer: SyntaxContext) -> Option<Span> { (outer_span.ctxt() == outer).then_some(outer_span) } -/// Removes block comments from the given `Vec` of lines. -/// -/// # Examples -/// -/// ```rust,ignore -/// without_block_comments(vec!["/*", "foo", "*/"]); -/// // => vec![] -/// -/// without_block_comments(vec!["bar", "/*", "foo", "*/"]); -/// // => vec!["bar"] -/// ``` -pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> { - let mut without = vec![]; - - let mut nest_level = 0; - - for line in lines { - if line.contains("/*") { - nest_level += 1; - continue; - } else if line.contains("*/") { - nest_level -= 1; - continue; - } - - if nest_level == 0 { - without.push(line); - } - } - - without -} - /// Trims the whitespace from the start and the end of the span. pub fn trim_span(sm: &SourceMap, span: Span) -> Span { let data = span.data(); @@ -758,15 +725,12 @@ pub fn str_literal_to_char_literal( &snip[1..(snip.len() - 1)] }; - let hint = format!( - "'{}'", - match ch { - "'" => "\\'", - r"\" => "\\\\", - "\\\"" => "\"", // no need to escape `"` in `'"'` - _ => ch, - } - ); + let hint = format!("'{}'", match ch { + "'" => "\\'", + r"\" => "\\\\", + "\\\"" => "\"", // no need to escape `"` in `'"'` + _ => ch, + }); Some(hint) } else { @@ -776,7 +740,7 @@ pub fn str_literal_to_char_literal( #[cfg(test)] mod test { - use super::{reindent_multiline, without_block_comments}; + use super::reindent_multiline; #[test] fn test_reindent_multiline_single_line() { @@ -844,29 +808,4 @@ mod test { z }".into(), true, Some(8))); } - - #[test] - fn test_without_block_comments_lines_without_block_comments() { - let result = without_block_comments(vec!["/*", "", "*/"]); - println!("result: {result:?}"); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); - assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); - - let result = without_block_comments(vec!["/* rust", "", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* one-line comment */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["foo", "bar", "baz"]); - assert_eq!(result, vec!["foo", "bar", "baz"]); - } } diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs index 421b25a77fe..1588ee452da 100644 --- a/src/tools/clippy/clippy_utils/src/str_utils.rs +++ b/src/tools/clippy/clippy_utils/src/str_utils.rs @@ -370,9 +370,11 @@ mod test { assert_eq!(camel_case_split("AbcDef"), vec!["Abc", "Def"]); assert_eq!(camel_case_split("Abc"), vec!["Abc"]); assert_eq!(camel_case_split("abcDef"), vec!["abc", "Def"]); - assert_eq!( - camel_case_split("\u{f6}\u{f6}AabABcd"), - vec!["\u{f6}\u{f6}", "Aab", "A", "Bcd"] - ); + assert_eq!(camel_case_split("\u{f6}\u{f6}AabABcd"), vec![ + "\u{f6}\u{f6}", + "Aab", + "A", + "Bcd" + ]); } } diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 0f86d89c980..3255c51d009 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -180,8 +180,10 @@ impl<'a> Sugg<'a> { ) -> Self { use rustc_ast::ast::RangeLimits; + let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0; + match expr.kind { - _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), + _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet(expr.span)), ast::ExprKind::AddrOf(..) | ast::ExprKind::Closure { .. } | ast::ExprKind::If(..) @@ -224,46 +226,38 @@ impl<'a> Sugg<'a> { | ast::ExprKind::While(..) | ast::ExprKind::Await(..) | ast::ExprKind::Err(_) - | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), + | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( AssocOp::DotDot, - lhs.as_ref().map_or("".into(), |lhs| { - snippet_with_context(cx, lhs.span, ctxt, default, app).0 - }), - rhs.as_ref().map_or("".into(), |rhs| { - snippet_with_context(cx, rhs.span, ctxt, default, app).0 - }), + lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), + rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), ), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp( AssocOp::DotDotEq, - lhs.as_ref().map_or("".into(), |lhs| { - snippet_with_context(cx, lhs.span, ctxt, default, app).0 - }), - rhs.as_ref().map_or("".into(), |rhs| { - snippet_with_context(cx, rhs.span, ctxt, default, app).0 - }), + lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), + rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), ), ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp( AssocOp::Assign, - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp( astbinop2assignop(op), - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp( AssocOp::from_ast_binop(op.node), - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::Cast(ref lhs, ref ty) | //FIXME(chenyukang), remove this after type ascription is removed from AST ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp( AssocOp::As, - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, ty.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(ty.span), ), } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 585134209ca..775a98fe361 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -12,8 +12,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; -use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::ConstValue; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ @@ -22,7 +22,7 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, Symbol, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_target::abi::VariantIdx; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; @@ -606,10 +606,13 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), // Unions are always fine right now. // This includes MaybeUninit, the main way people use uninitialized memory. - // For ADTs, we could look at all fields just like for tuples, but that's potentially - // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to - // just use an `#[allow()]`. - ty::Adt(adt, _) => adt.is_union(), + ty::Adt(adt, _) if adt.is_union() => true, + // Types (e.g. `UnsafeCell<MaybeUninit<T>>`) that recursively contain only types that can be uninit + // can themselves be uninit too. + // This purposefully ignores enums as they may have a discriminant that can't be uninit. + ty::Adt(adt, args) if adt.is_struct() => adt + .all_fields() + .all(|field| is_uninit_value_valid_for_ty(cx, field.ty(cx.tcx, args))), // For the rest, conservatively assume that they cannot be uninit. _ => false, } diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index 875ddec259e..e612e9c6cb6 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -14,14 +14,14 @@ use crate::def_path_res; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{walk_qpath, walk_ty, Visitor}; +use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty}; use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty}; use rustc_span::{Span, Symbol}; mod certainty; -use certainty::{join, meet, Certainty, Meet}; +use certainty::{Certainty, Meet, join, meet}; pub fn expr_type_is_certain(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { expr_type_certainty(cx, expr).is_certain() diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index fbf3d95365a..1230b60c3a6 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -1,4 +1,4 @@ -use crate::visitors::{for_each_expr, for_each_expr_without_closures, Descend, Visitable}; +use crate::visitors::{Descend, Visitable, for_each_expr, for_each_expr_without_closures}; use crate::{self as utils, get_enclosing_loop_or_multi_call_closure}; use core::ops::ControlFlow; use hir::def::Res; diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index e5b6d3965e9..6d9a85a1181 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -1,10 +1,10 @@ use crate::ty::needs_ordered_drop; use crate::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; -use rustc_ast::visit::{try_visit, VisitorResult}; +use rustc_ast::visit::{VisitorResult, try_visit}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; +use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr}; use rustc_hir::{ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, Safety, Stmt, UnOp, UnsafeSource, |
