diff options
50 files changed, 357 insertions, 142 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 71e498c301b..1b792736a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3641,6 +3641,7 @@ Released 2018-09-13 [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons +[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements diff --git a/book/README.md b/book/README.md index b652194d0d1..6d67f80ff25 100644 --- a/book/README.md +++ b/book/README.md @@ -1,4 +1,4 @@ # Clippy Book This is the source for the Clippy Book. See the -[book](src/infrastructure/book.md) for more information. +[book](src/development/infrastructure/book.md) for more information. diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index e560f4c6a3e..80a47affe30 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -95,6 +95,9 @@ As section headers, we use: Please also be sure to update the Beta/Unreleased sections at the top with the relevant commit ranges. +If you have the time, it would be appreciated if you double-check, that the +`#[clippy::version]` attributes for the added lints contains the correct version. + [changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md [forge]: https://forge.rust-lang.org/ [rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 2e0659f42d7..c089f4d8ce4 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -553,7 +553,7 @@ fn replace_ident_like(contents: &str, replacements: &[(&str, &str)]) -> Option<S pos = m.end(); } result.push_str(&contents[pos..]); - edited.then(|| result) + edited.then_some(result) } fn round_to_fifty(count: usize) -> usize { diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index eee5f90d178..1761360fb28 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -161,7 +161,7 @@ declare_clippy_lint! { /// baz().await; // Lint violation /// } /// ``` - #[clippy::version = "1.49.0"] + #[clippy::version = "1.62.0"] pub AWAIT_HOLDING_INVALID_TYPE, suspicious, "holding a type across an await point which is not allowed to be held as per the configuration" diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 02c2f30a4dd..af3798a0cc8 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -500,7 +500,7 @@ declare_clippy_lint! { /// let x: i32 = -42; /// let y: u32 = x.unsigned_abs(); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub CAST_ABS_TO_UNSIGNED, suspicious, "casting the result of `abs()` to an unsigned integer can panic" diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 9b8a481b6ea..f6ec8fe7edc 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -43,7 +43,7 @@ declare_clippy_lint! { /// #[allow(clippy::crate_in_macro_def)] /// macro_rules! ok { ... crate::foo ... } /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub CRATE_IN_MACRO_DEF, suspicious, "using `crate` in a macro definition" diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index d6bd43a7494..6dddb969f33 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{ - self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, GenericArg, HirId, ImplItem, + self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem, TraitItemKind, TyKind, UnOp, }; @@ -717,20 +717,36 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind { ExprKind::Ret(_) => { - let output = cx - .tcx - .fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap())) - .skip_binder() - .output(); - Some(if !output.is_ref() { - Position::Other(precedence) - } else if output.has_placeholders() || output.has_opaque_types() { - Position::ReborrowStable(precedence) - } else { - Position::DerefStable(precedence) - }) + let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap()); + Some( + if let Node::Expr(Expr { + kind: ExprKind::Closure { fn_decl, .. }, + .. + }) = cx.tcx.hir().get(owner_id) + { + match fn_decl.output { + FnRetTy::Return(ty) => binding_ty_auto_deref_stability(ty, precedence), + FnRetTy::DefaultReturn(_) => Position::Other(precedence), + } + } else { + let output = cx + .tcx + .fn_sig(cx.tcx.hir().local_def_id(owner_id)) + .skip_binder() + .output(); + if !output.is_ref() { + Position::Other(precedence) + } else if output.has_placeholders() || output.has_opaque_types() { + Position::ReborrowStable(precedence) + } else { + Position::DerefStable(precedence) + } + }, + ) + }, + ExprKind::Call(func, _) if func.hir_id == child_id => { + (child_id == e.hir_id).then_some(Position::Callee) }, - ExprKind::Call(func, _) if func.hir_id == child_id => (child_id == e.hir_id).then(|| Position::Callee), ExprKind::Call(func, args) => args .iter() .position(|arg| arg.hir_id == child_id) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 25014bfa1a5..b35f0b8ca52 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -116,7 +116,7 @@ declare_clippy_lint! { /// let x = Foo; /// std::mem::drop(x); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub DROP_NON_DROP, suspicious, "call to `std::mem::drop` with a value which does not implement `Drop`" @@ -136,7 +136,7 @@ declare_clippy_lint! { /// let x = Foo; /// std::mem::forget(x); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub FORGET_NON_DROP, suspicious, "call to `std::mem::forget` with a value which does not implement `Drop`" diff --git a/clippy_lints/src/empty_drop.rs b/clippy_lints/src/empty_drop.rs index 325ae2356c1..ec063c0f777 100644 --- a/clippy_lints/src/empty_drop.rs +++ b/clippy_lints/src/empty_drop.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// ```rust /// struct S; /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub EMPTY_DROP, restriction, "empty `Drop` implementations" diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 27743a0ebec..4e3ae4c9614 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -650,7 +650,7 @@ fn find_insert_calls<'tcx>( let allow_insert_closure = s.allow_insert_closure; let is_single_insert = s.is_single_insert; let edits = s.edits; - s.can_use_entry.then(|| InsertSearchResults { + s.can_use_entry.then_some(InsertSearchResults { edits, allow_insert_closure, is_single_insert, diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 6a031a627df..c5abcc46254 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -127,7 +127,7 @@ fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option<Span> { (!span.from_expansion() && impl_item.generics.params.is_empty() && !is_lint_allowed(cx, MULTIPLE_INHERENT_IMPL, id)) - .then(|| span) + .then_some(span) } else { None } diff --git a/clippy_lints/src/invalid_utf8_in_unchecked.rs b/clippy_lints/src/invalid_utf8_in_unchecked.rs new file mode 100644 index 00000000000..e0a607f9a95 --- /dev/null +++ b/clippy_lints/src/invalid_utf8_in_unchecked.rs @@ -0,0 +1,74 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::{match_function_call, paths}; +use rustc_ast::{BorrowKind, LitKind}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Spanned; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `std::str::from_utf8_unchecked` with an invalid UTF-8 literal + /// + /// ### Why is this bad? + /// Creating such a `str` would result in undefined behavior + /// + /// ### Example + /// ```rust + /// # #[allow(unused)] + /// unsafe { + /// std::str::from_utf8_unchecked(b"cl\x82ippy"); + /// } + /// ``` + #[clippy::version = "1.64.0"] + pub INVALID_UTF8_IN_UNCHECKED, + correctness, + "using a non UTF-8 literal in `std::std::from_utf8_unchecked`" +} +declare_lint_pass!(InvalidUtf8InUnchecked => [INVALID_UTF8_IN_UNCHECKED]); + +impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) { + match &arg.kind { + ExprKind::Lit(Spanned { node: lit, .. }) => { + if let LitKind::ByteStr(bytes) = &lit + && std::str::from_utf8(bytes).is_err() + { + lint(cx, expr.span); + } + }, + ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => { + let elements = args.iter().map(|e|{ + match &e.kind { + ExprKind::Lit(Spanned { node: lit, .. }) => match lit { + LitKind::Byte(b) => Some(*b), + #[allow(clippy::cast_possible_truncation)] + LitKind::Int(b, _) => Some(*b as u8), + _ => None + } + _ => None + } + }).collect::<Option<Vec<_>>>(); + + if let Some(elements) = elements + && std::str::from_utf8(&elements).is_err() + { + lint(cx, expr.span); + } + } + _ => {} + } + } + } +} + +fn lint(cx: &LateContext<'_>, span: Span) { + span_lint( + cx, + INVALID_UTF8_IN_UNCHECKED, + span, + "non UTF-8 literal in `std::str::from_utf8_unchecked`", + ); +} diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index 563ad891603..da26a3f0130 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -92,6 +92,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS), LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(int_plus_one::INT_PLUS_ONE), + LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED), LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(len_zero::COMPARISON_TO_EMPTY), diff --git a/clippy_lints/src/lib.register_correctness.rs b/clippy_lints/src/lib.register_correctness.rs index 7d5e65cb27a..9975859c54f 100644 --- a/clippy_lints/src/lib.register_correctness.rs +++ b/clippy_lints/src/lib.register_correctness.rs @@ -29,6 +29,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(infinite_iter::INFINITE_ITER), LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), + LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED), LintId::of(let_underscore::LET_UNDERSCORE_LOCK), LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), LintId::of(loops::ITER_NEXT_LOOP), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index d3c75f8b519..ceb8470657f 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -196,6 +196,7 @@ store.register_lints(&[ inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS, + invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED, items_after_statements::ITEMS_AFTER_STATEMENTS, iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR, large_const_arrays::LARGE_CONST_ARRAYS, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 172fdf8c852..1604d1078ee 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -255,6 +255,7 @@ mod init_numbered_fields; mod inline_fn_without_body; mod int_plus_one; mod invalid_upcast_comparisons; +mod invalid_utf8_in_unchecked; mod items_after_statements; mod iter_not_returning_iterator; mod large_const_arrays; @@ -913,6 +914,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv))); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold))); + store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 4278e98dc91..2b04475c7a9 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { (matches!(v.data, hir::VariantData::Unit(_)) && v.ident.as_str().starts_with('_') && is_doc_hidden(cx.tcx.hir().attrs(v.id))) - .then(|| (id, v.span)) + .then_some((id, v.span)) }); if let Some((id, span)) = iter.next() && iter.next().is_none() diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs index 542905a2d76..8f98b43b9e5 100644 --- a/clippy_lints/src/matches/manual_map.rs +++ b/clippy_lints/src/matches/manual_map.rs @@ -105,7 +105,7 @@ fn check<'tcx>( // Determine which binding mode to use. let explicit_ref = some_pat.contains_explicit_ref_binding(); - let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability)); + let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then_some(ty_mutability)); let as_ref_str = match binding_ref { Some(Mutability::Mut) => ".as_mut()", diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index 15513de7d86..61d28b15066 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { normalized_pats[i + 1..] .iter() .enumerate() - .find_map(|(j, other)| pat.has_overlapping_values(other).then(|| i + 1 + j)) + .find_map(|(j, other)| pat.has_overlapping_values(other).then_some(i + 1 + j)) .unwrap_or(normalized_pats.len()) }) .collect(); @@ -55,7 +55,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { .zip(forwards_blocking_idxs[..i].iter().copied().rev()) .skip_while(|&(_, forward_block)| forward_block > i) .find_map(|((j, other), forward_block)| { - (forward_block == i || pat.has_overlapping_values(other)).then(|| j) + (forward_block == i || pat.has_overlapping_values(other)).then_some(j) }) .unwrap_or(0) }) diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index b2a873ef582..5c996bc33f3 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -1061,7 +1061,7 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar let start = scrutinee_span.hi(); let mut arm_spans = arms.iter().map(|arm| { let data = arm.span.data(); - (data.ctxt == SyntaxContext::root()).then(|| (data.lo, data.hi)) + (data.ctxt == SyntaxContext::root()).then_some((data.lo, data.hi)) }); let end = e.span.hi(); @@ -1095,7 +1095,7 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar parent: None, } .span(); - (!span_contains_cfg(cx, span)).then(|| next_start).ok_or(()) + (!span_contains_cfg(cx, span)).then_some(next_start).ok_or(()) }); match found { Ok(start) => { diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 68a75667914..46d2fc493f8 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -43,7 +43,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> { Some(RepeatKind::String) } else { let ty = ty.peel_refs(); - (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then(|| RepeatKind::String) + (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then_some(RepeatKind::String) } } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index cc1530f0ed0..29ec6e04286 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -369,7 +369,7 @@ declare_clippy_lint! { /// let x: Result<u32, &str> = Ok(10); /// x.expect_err("Testing expect_err"); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub ERR_EXPECT, style, r#"using `.err().expect("")` when `.expect_err("")` can be used"# @@ -2215,7 +2215,7 @@ declare_clippy_lint! { /// c.is_ascii_digit(); /// c.is_ascii_hexdigit(); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub IS_DIGIT_ASCII_RADIX, style, "use of `char::is_digit(..)` with literal radix of 10 or 16" @@ -2235,7 +2235,7 @@ declare_clippy_lint! { /// let x = Some(3); /// x.as_ref(); /// ``` - #[clippy::version = "1.61.0"] + #[clippy::version = "1.62.0"] pub NEEDLESS_OPTION_TAKE, complexity, "using `.as_ref().take()` on a temporary value" @@ -2737,6 +2737,12 @@ impl Methods { } }, ("take", []) => needless_option_take::check(cx, expr, recv), + ("then", [arg]) => { + if !meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) { + return; + } + unnecessary_lazy_eval::check(cx, expr, recv, arg, "then_some"); + }, ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => { implicit_clone::check(cx, name, expr, recv); }, diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 865f6d0318e..a9c641b4606 100644 --- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -20,8 +20,9 @@ pub(super) fn check<'tcx>( ) { let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); + let is_bool = cx.typeck_results().expr_ty(recv).is_bool(); - if is_option || is_result { + if is_option || is_result || is_bool { if let hir::ExprKind::Closure { body, .. } = arg.kind { let body = cx.tcx.hir().body(body); let body_expr = &body.value; @@ -33,8 +34,10 @@ pub(super) fn check<'tcx>( if eager_or_lazy::switch_to_eager_eval(cx, body_expr) { let msg = if is_option { "unnecessary closure used to substitute value for `Option::None`" - } else { + } else if is_result { "unnecessary closure used to substitute value for `Result::Err`" + } else { + "unnecessary closure used with `bool::then`" }; let applicability = if body .params diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 093ec389335..5c45ee6d94a 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -88,15 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // shouldn't be implemented when it is hidden in docs return; } - if impl_item - .generics - .params - .iter() - .any(|gen| matches!(gen.kind, hir::GenericParamKind::Type { .. })) - { - // when the result of `new()` depends on a type parameter we should not require - // an - // impl of `Default` + if !impl_item.generics.params.is_empty() { + // when the result of `new()` depends on a parameter we should not require + // an impl of `Default` return; } if_chain! { diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index ea5a8f0858b..44f153cffac 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -146,7 +146,7 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> }); if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind { match some_captures.get(local_id) - .or_else(|| (method_sugg == "map_or_else").then(|| ()).and_then(|_| none_captures.get(local_id))) + .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|_| none_captures.get(local_id))) { Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 25b73918c0a..8bacc6f6b32 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -501,7 +501,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio .iter() .filter_map(get_rptr_lm) .filter(|&(lt, _, _)| lt.name == out.name) - .map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span)) + .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span)) .collect(); if let Some(args) = args && !args.is_empty() diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index bf318c055da..5dcdab5b8ab 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -99,7 +99,7 @@ declare_clippy_lint! { #[derive(Default)] pub(crate) struct Shadow { - bindings: Vec<FxHashMap<Symbol, Vec<ItemLocalId>>>, + bindings: Vec<(FxHashMap<Symbol, Vec<ItemLocalId>>, LocalDefId)>, } impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { let HirId { owner, local_id } = id; // get (or insert) the list of items for this owner and symbol - let data = self.bindings.last_mut().unwrap(); + let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap(); let items_with_name = data.entry(ident.name).or_default(); // check other bindings with the same name, most recently seen first @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { return; } - if is_shadow(cx, owner, prev, local_id) { + if is_shadow(cx, scope_owner, prev, local_id) { let prev_hir_id = HirId { owner, local_id: prev }; lint_shadow(cx, pat, prev_hir_id, ident.span); // only lint against the "nearest" shadowed binding @@ -144,11 +144,9 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { let hir = cx.tcx.hir(); - if !matches!( - hir.body_owner_kind(hir.body_owner_def_id(body.id())), - BodyOwnerKind::Closure - ) { - self.bindings.push(FxHashMap::default()); + let owner_id = hir.body_owner_def_id(body.id()); + if !matches!(hir.body_owner_kind(owner_id), BodyOwnerKind::Closure) { + self.bindings.push((FxHashMap::default(), owner_id)); } } diff --git a/clippy_lints/src/swap_ptr_to_ref.rs b/clippy_lints/src/swap_ptr_to_ref.rs index 75d3b040c96..3cbbda80f3a 100644 --- a/clippy_lints/src/swap_ptr_to_ref.rs +++ b/clippy_lints/src/swap_ptr_to_ref.rs @@ -73,7 +73,7 @@ fn is_ptr_to_ref(cx: &LateContext<'_>, e: &Expr<'_>, ctxt: SyntaxContext) -> (bo && let ExprKind::Unary(UnOp::Deref, derefed_expr) = borrowed_expr.kind && cx.typeck_results().expr_ty(derefed_expr).is_unsafe_ptr() { - (true, (borrowed_expr.span.ctxt() == ctxt || derefed_expr.span.ctxt() == ctxt).then(|| derefed_expr.span)) + (true, (borrowed_expr.span.ctxt() == ctxt || derefed_expr.span.ctxt() == ctxt).then_some(derefed_expr.span)) } else { (false, None) } diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 025dd57e83a..04f16fd2161 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -265,14 +265,28 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span } } +fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> { + let body = cx.enclosing_body?; + let map = cx.tcx.hir(); + let mut span = map.body(body).value.span; + for (_, node) in map.parent_iter(body.hir_id) { + match node { + Node::Expr(e) => span = e.span, + Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (), + _ => break, + } + } + Some(span) +} + fn span_in_body_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { let source_map = cx.sess().source_map(); let ctxt = span.ctxt(); if ctxt == SyntaxContext::root() - && let Some(body) = cx.enclosing_body + && let Some(search_span) = get_body_search_span(cx) { if let Ok(unsafe_line) = source_map.lookup_line(span.lo()) - && let Some(body_span) = walk_span_to_context(cx.tcx.hir().body(body).value.span, SyntaxContext::root()) + && let Some(body_span) = walk_span_to_context(search_span, SyntaxContext::root()) && let Ok(body_line) = source_map.lookup_line(body_span.lo()) && Lrc::ptr_eq(&unsafe_line.sf, &body_line.sf) && let Some(src) = unsafe_line.sf.src.as_deref() diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 6518e0a6ea0..3010fc0223c 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -843,7 +843,7 @@ fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> { fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> { DEFAULT_LINT_LEVELS .iter() - .find_map(|(group_name, group_level)| (*group_name == lint_group).then(|| *group_level)) + .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level)) } pub(super) fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 67b2bc8c3f3..08b88947520 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -515,7 +515,7 @@ impl Write { args.push(arg, span); } - parser.errors.is_empty().then(move || args) + parser.errors.is_empty().then_some(args) } /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9fa28e137f9..0e739303683 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1016,7 +1016,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' captures: HirIdMap::default(), }; v.visit_expr(expr); - v.allow_closure.then(|| v.captures) + v.allow_closure.then_some(v.captures) } /// Returns the method names and argument list of nested method call expressions that make up diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index b09c929f76e..9e238c6f1ac 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -12,6 +12,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,62,0 { BOOL_THEN_SOME } 1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN } 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 6542e77113b..05429d05d9e 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -163,6 +163,7 @@ pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"]; pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"]; pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"]; pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"]; +pub const STR_FROM_UTF8_UNCHECKED: [&str; 4] = ["core", "str", "converts", "from_utf8_unchecked"]; pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"]; pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"]; #[cfg(feature = "internal")] diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index f88a92fb11c..1197fe914de 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -353,7 +353,7 @@ pub fn snippet_with_context<'a>( /// span containing `m!(0)`. pub fn walk_span_to_context(span: Span, outer: SyntaxContext) -> Option<Span> { let outer_span = hygiene::walk_chain(span, outer); - (outer_span.ctxt() == outer).then(|| outer_span) + (outer_span.ctxt() == outer).then_some(outer_span) } /// Removes block comments from the given `Vec` of lines. diff --git a/tests/ui/cast_size_32bit.stderr b/tests/ui/cast_size_32bit.stderr index 7125f741c15..8990c3ba739 100644 --- a/tests/ui/cast_size_32bit.stderr +++ b/tests/ui/cast_size_32bit.stderr @@ -114,5 +114,5 @@ LL | 3_999_999_999usize as f64; | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` -error: aborting due to 20 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed index d4ff1b1566d..a650fdc1f89 100644 --- a/tests/ui/explicit_auto_deref.fixed +++ b/tests/ui/explicit_auto_deref.fixed @@ -211,4 +211,8 @@ fn main() { unsafe { var(0, &**x); } + + let s = &"str"; + let _ = || return *s; + let _ = || -> &'static str { return s }; } diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs index 99294a7947b..8f4f352576a 100644 --- a/tests/ui/explicit_auto_deref.rs +++ b/tests/ui/explicit_auto_deref.rs @@ -211,4 +211,8 @@ fn main() { unsafe { var(0, &**x); } + + let s = &"str"; + let _ = || return *s; + let _ = || -> &'static str { return *s }; } diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr index 55f956e37ae..92765307ea7 100644 --- a/tests/ui/explicit_auto_deref.stderr +++ b/tests/ui/explicit_auto_deref.stderr @@ -192,5 +192,11 @@ error: deref which would be done by auto-deref LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference | ^^^^^^^^^^ help: try this: `ref_str` -error: aborting due to 32 previous errors +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:217:41 + | +LL | let _ = || -> &'static str { return *s }; + | ^^ help: try this: `s` + +error: aborting due to 33 previous errors diff --git a/tests/ui/invalid_utf8_in_unchecked.rs b/tests/ui/invalid_utf8_in_unchecked.rs new file mode 100644 index 00000000000..3dc096d3197 --- /dev/null +++ b/tests/ui/invalid_utf8_in_unchecked.rs @@ -0,0 +1,20 @@ +#![warn(clippy::invalid_utf8_in_unchecked)] + +fn main() { + // Valid + unsafe { + std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]); + std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']); + std::str::from_utf8_unchecked(b"clippy"); + + let x = 0xA0; + std::str::from_utf8_unchecked(&[0xC0, x]); + } + + // Invalid + unsafe { + std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); + std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + std::str::from_utf8_unchecked(b"cl\x82ippy"); + } +} diff --git a/tests/ui/invalid_utf8_in_unchecked.stderr b/tests/ui/invalid_utf8_in_unchecked.stderr new file mode 100644 index 00000000000..c89cd2758ee --- /dev/null +++ b/tests/ui/invalid_utf8_in_unchecked.stderr @@ -0,0 +1,22 @@ +error: non UTF-8 literal in `std::str::from_utf8_unchecked` + --> $DIR/invalid_utf8_in_unchecked.rs:16:9 + | +LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::invalid-utf8-in-unchecked` implied by `-D warnings` + +error: non UTF-8 literal in `std::str::from_utf8_unchecked` + --> $DIR/invalid_utf8_in_unchecked.rs:17:9 + | +LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'/x82', b'i', b'p', b'p', b'y']); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: non UTF-8 literal in `std::str::from_utf8_unchecked` + --> $DIR/invalid_utf8_in_unchecked.rs:18:9 + | +LL | std::str::from_utf8_unchecked(b"cl/x82ippy"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 538927b1805..65809023f8d 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -212,3 +212,17 @@ impl DocHidden { } fn main() {} + +pub struct IgnoreConstGenericNew(usize); +impl IgnoreConstGenericNew { + pub fn new<const N: usize>() -> Self { + Self(N) + } +} + +pub struct IgnoreLifetimeNew; +impl IgnoreLifetimeNew { + pub fn new<'a>() -> Self { + Self + } +} diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 3bd41d06260..43d76094d0e 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -265,5 +265,17 @@ note: previous binding is here LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ -error: aborting due to 22 previous errors +error: `x` shadows a previous, unrelated binding + --> $DIR/shadow.rs:94:21 + | +LL | if let Some(x) = Some(1) { x } else { 1 } + | ^ + | +note: previous binding is here + --> $DIR/shadow.rs:93:13 + | +LL | let x = 1; + | ^ + +error: aborting due to 23 previous errors diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index 33b6a82f9d2..08aee433215 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -250,6 +250,11 @@ fn from_proc_macro() { proc_macro_unsafe::unsafe_block!(token); } +fn in_closure(x: *const u32) { + // Safety: reason + let _ = || unsafe { *x }; +} + // Invalid comments #[rustfmt::skip] @@ -351,9 +356,9 @@ mod unsafe_impl_smoke_test { #[rustfmt::skip] mod sub_mod2 { - // + // // SAFETY: ok - // + // unsafe impl B for (u32) {} unsafe trait B {} diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr index b79949e9d06..c6a2127443b 100644 --- a/tests/ui/undocumented_unsafe_blocks.stderr +++ b/tests/ui/undocumented_unsafe_blocks.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:257:19 + --> $DIR/undocumented_unsafe_blocks.rs:262:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | /* Safety: */ unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:261:5 + --> $DIR/undocumented_unsafe_blocks.rs:266:5 | LL | unsafe {} | ^^^^^^^^^ @@ -16,7 +16,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:265:14 + --> $DIR/undocumented_unsafe_blocks.rs:270:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:265:29 + --> $DIR/undocumented_unsafe_blocks.rs:270:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:265:48 + --> $DIR/undocumented_unsafe_blocks.rs:270:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:269:18 + --> $DIR/undocumented_unsafe_blocks.rs:274:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:269:37 + --> $DIR/undocumented_unsafe_blocks.rs:274:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:273:14 + --> $DIR/undocumented_unsafe_blocks.rs:278:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:278:19 + --> $DIR/undocumented_unsafe_blocks.rs:283:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:284:14 + --> $DIR/undocumented_unsafe_blocks.rs:289:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:288:14 + --> $DIR/undocumented_unsafe_blocks.rs:293:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:292:13 + --> $DIR/undocumented_unsafe_blocks.rs:297:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:302:8 + --> $DIR/undocumented_unsafe_blocks.rs:307:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -104,7 +104,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:308:13 + --> $DIR/undocumented_unsafe_blocks.rs:313:13 | LL | unsafe {} | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:316:5 + --> $DIR/undocumented_unsafe_blocks.rs:321:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -124,7 +124,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:320:5 + --> $DIR/undocumented_unsafe_blocks.rs:325:5 | LL | unsafe { | ^^^^^^^^ @@ -132,7 +132,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:330:5 + --> $DIR/undocumented_unsafe_blocks.rs:335:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -140,7 +140,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:334:20 + --> $DIR/undocumented_unsafe_blocks.rs:339:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:341:5 + --> $DIR/undocumented_unsafe_blocks.rs:346:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:348:9 + --> $DIR/undocumented_unsafe_blocks.rs:353:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -164,7 +164,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:369:13 + --> $DIR/undocumented_unsafe_blocks.rs:374:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:394:13 + --> $DIR/undocumented_unsafe_blocks.rs:399:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,7 +188,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:402:5 + --> $DIR/undocumented_unsafe_blocks.rs:407:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:394:13 + --> $DIR/undocumented_unsafe_blocks.rs:399:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:408:5 + --> $DIR/undocumented_unsafe_blocks.rs:413:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +216,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:454:5 + --> $DIR/undocumented_unsafe_blocks.rs:459:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -224,7 +224,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:458:19 + --> $DIR/undocumented_unsafe_blocks.rs:463:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:462:5 + --> $DIR/undocumented_unsafe_blocks.rs:467:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:467:5 + --> $DIR/undocumented_unsafe_blocks.rs:472:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -248,7 +248,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:474:5 + --> $DIR/undocumented_unsafe_blocks.rs:479:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -256,7 +256,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:483:1 + --> $DIR/undocumented_unsafe_blocks.rs:488:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index 65fcdc43061..eed81796883 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -30,6 +30,7 @@ fn main() { let ext_opt = Some(42); let nested_opt = Some(Some(42)); let nested_tuple_opt = Some(Some((42, 43))); + let cond = true; // Should lint - Option let _ = opt.unwrap_or(2); @@ -42,6 +43,7 @@ fn main() { let _ = opt.get_or_insert(2); let _ = opt.ok_or(2); let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); + let _ = cond.then_some(astronomers_pi); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 206080ed69a..1588db79b38 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -30,6 +30,7 @@ fn main() { let ext_opt = Some(42); let nested_opt = Some(Some(42)); let nested_tuple_opt = Some(Some((42, 43))); + let cond = true; // Should lint - Option let _ = opt.unwrap_or_else(|| 2); @@ -42,6 +43,7 @@ fn main() { let _ = opt.get_or_insert_with(|| 2); let _ = opt.ok_or_else(|| 2); let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); + let _ = cond.then(|| astronomers_pi); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 7e4dd7730e7..83dc7fd832c 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:35:13 + --> $DIR/unnecessary_lazy_eval.rs:36:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:36:13 + --> $DIR/unnecessary_lazy_eval.rs:37:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:37:13 + --> $DIR/unnecessary_lazy_eval.rs:38:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:39:13 + --> $DIR/unnecessary_lazy_eval.rs:40:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:40:13 + --> $DIR/unnecessary_lazy_eval.rs:41:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:41:13 + --> $DIR/unnecessary_lazy_eval.rs:42:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:42:13 + --> $DIR/unnecessary_lazy_eval.rs:43:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:43:13 + --> $DIR/unnecessary_lazy_eval.rs:44:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -65,15 +65,23 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:44:13 + --> $DIR/unnecessary_lazy_eval.rs:45:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- | | | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:46:13 + | +LL | let _ = cond.then(|| astronomers_pi); + | ^^^^^----------------------- + | | + | help: use `then_some(..)` instead: `then_some(astronomers_pi)` + error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:47:13 + --> $DIR/unnecessary_lazy_eval.rs:49:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- @@ -81,7 +89,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:48:13 + --> $DIR/unnecessary_lazy_eval.rs:50:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -89,7 +97,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:49:28 + --> $DIR/unnecessary_lazy_eval.rs:51:28 | LL | let _: Option<usize> = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -97,7 +105,7 @@ LL | let _: Option<usize> = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:50:13 + --> $DIR/unnecessary_lazy_eval.rs:52:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -105,7 +113,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:51:35 + --> $DIR/unnecessary_lazy_eval.rs:53:35 | LL | let _: Result<usize, usize> = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -113,7 +121,7 @@ LL | let _: Result<usize, usize> = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:52:28 + --> $DIR/unnecessary_lazy_eval.rs:54:28 | LL | let _: Option<usize> = None.or_else(|| None); | ^^^^^---------------- @@ -121,7 +129,7 @@ LL | let _: Option<usize> = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:55:13 + --> $DIR/unnecessary_lazy_eval.rs:57:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -129,7 +137,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:56:13 + --> $DIR/unnecessary_lazy_eval.rs:58:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -137,7 +145,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:57:13 + --> $DIR/unnecessary_lazy_eval.rs:59:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -145,7 +153,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:58:13 + --> $DIR/unnecessary_lazy_eval.rs:60:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -153,7 +161,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:59:13 + --> $DIR/unnecessary_lazy_eval.rs:61:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -161,7 +169,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:79:28 + --> $DIR/unnecessary_lazy_eval.rs:81:28 | LL | let _: Option<usize> = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -169,7 +177,7 @@ LL | let _: Option<usize> = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:80:13 + --> $DIR/unnecessary_lazy_eval.rs:82:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -177,7 +185,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:81:13 + --> $DIR/unnecessary_lazy_eval.rs:83:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -185,7 +193,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:87:13 + --> $DIR/unnecessary_lazy_eval.rs:89:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -193,7 +201,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:88:13 + --> $DIR/unnecessary_lazy_eval.rs:90:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -201,7 +209,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:89:13 + --> $DIR/unnecessary_lazy_eval.rs:91:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -209,7 +217,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:111:35 + --> $DIR/unnecessary_lazy_eval.rs:113:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -217,7 +225,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:112:35 + --> $DIR/unnecessary_lazy_eval.rs:114:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -225,7 +233,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:113:35 + --> $DIR/unnecessary_lazy_eval.rs:115:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -233,7 +241,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:115:35 + --> $DIR/unnecessary_lazy_eval.rs:117:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -241,7 +249,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:116:35 + --> $DIR/unnecessary_lazy_eval.rs:118:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -249,7 +257,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:117:35 + --> $DIR/unnecessary_lazy_eval.rs:119:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -257,7 +265,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:118:35 + --> $DIR/unnecessary_lazy_eval.rs:120:35 | LL | let _: Result<usize, usize> = res. | ___________________________________^ @@ -271,5 +279,5 @@ LL | | or_else(|_| Ok(ext_str.some_field)); | | | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` -error: aborting due to 33 previous errors +error: aborting due to 34 previous errors diff --git a/util/etc/vscode-tasks.json b/util/etc/vscode-tasks.json index e0074510c9f..ab98f9b4154 100644 --- a/util/etc/vscode-tasks.json +++ b/util/etc/vscode-tasks.json @@ -8,15 +8,15 @@ "problemMatcher": [], "group": { "kind": "build", - "isDefault": true, - }, + "isDefault": true + } }, { "label": "cargo dev fmt", "type": "shell", "command": "cargo dev fmt", "problemMatcher": [], - "group": "none", + "group": "none" }, { "label": "cargo uitest", @@ -24,19 +24,19 @@ "command": "cargo uitest", "options": { "env": { - "RUST_BACKTRACE": "1", // This task will usually execute all UI tests inside `tests/ui` you can // optionally uncomment the line below and only run a specific test. // // See: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md#testing // // "TESTNAME": "<TODO>", - }, + "RUST_BACKTRACE": "1" + } }, "problemMatcher": [], "group": { "kind": "test", - "isDefault": true, + "isDefault": true } }, { @@ -44,14 +44,14 @@ "type": "shell", "command": "cargo test", "problemMatcher": [], - "group": "test", + "group": "test" }, { "label": "cargo dev bless", "type": "shell", "command": "cargo dev bless", "problemMatcher": [], - "group": "none", - }, - ], + "group": "none" + } + ] } |
