From 14379c9b9f1fcac0ee9ed0910465087f5bb4e73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Aug 2024 18:40:45 +0000 Subject: [PATCH] [Experimental] `>::into` lint Running crater to see how common that pattern is. The Lint would have to be at most warn-by-default because there are a handful of cases detected that are actually perfectly reasonable (`type` aliases with per-platform `cfg`, or macros) which are now at best half-heartedly handled. I've detected a handful of cases where we're calling `.into()` unnecessarily in the `rustc` codebase as well, and changed those. --- compiler/rustc_ast/src/ast.rs | 6 +- .../src/const_eval/eval_queries.rs | 2 +- .../rustc_const_eval/src/interpret/call.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_lint/messages.ftl | 2 + compiler/rustc_lint/src/builtin.rs | 100 +++++++++++++++++- compiler/rustc_lint/src/lib.rs | 5 +- compiler/rustc_lint/src/lints.rs | 7 ++ compiler/rustc_lint/src/passes.rs | 12 +-- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 10 +- compiler/rustc_parse/src/parser/tests.rs | 6 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../src/traits/project.rs | 4 +- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/core/src/convert/mod.rs | 1 + library/std/src/os/fd/owned.rs | 2 +- .../src/sys/pal/unix/process/process_unix.rs | 1 + library/std/src/sys_common/process.rs | 1 + .../needless_return_with_question_mark.fixed | 2 +- .../ui/needless_return_with_question_mark.rs | 2 +- .../clippy/tests/ui/useless_conversion.stderr | 74 ++++++++++++- .../error-in-impl-trait/realistic-async.rs | 1 + .../issues/issue-83883-describe-lints.stdout | 1 + .../deriving/auxiliary/another-proc-macro.rs | 1 + .../macro-or-patterns-back-compat.fixed | 2 +- .../macros/macro-or-patterns-back-compat.rs | 2 +- .../macro-pat-pattern-followed-by-or.rs | 2 +- 31 files changed, 223 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a44ed82850480..9746e13b74e1b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3464,7 +3464,7 @@ impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { ForeignItemKind::Static(box static_foreign_item) => { - ItemKind::Static(Box::new(static_foreign_item.into())) + ItemKind::Static(Box::new(static_foreign_item)) } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), @@ -3478,9 +3478,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(box static_item) => { - ForeignItemKind::Static(Box::new(static_item.into())) - } + ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)), ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 96b3ec6f18728..4e1a488fc95f4 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -78,7 +78,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( ecx.push_stack_frame_raw( cid.instance, body, - &ret.clone().into(), + &ret.clone(), StackPopCleanup::Root { cleanup: false }, )?; ecx.storage_live_for_always_live_locals()?; diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 917a2fa7c6dd4..76e6f9b6fd1d3 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -854,7 +854,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { (Abi::Rust, fn_abi), &[FnArg::Copy(arg.into())], false, - &ret.into(), + &ret, Some(target), unwind, ) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7720faddba376..9e610cf3ed414 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2533,7 +2533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { other_generic_param.name.ident() == generic_param.name.ident() }, ) { - idxs_matched.push(other_idx.into()); + idxs_matched.push(other_idx); } if idxs_matched.is_empty() { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7a394a6d6c1ad..8707b7fa59b37 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -733,6 +733,8 @@ lint_reserved_prefix = prefix `{$prefix}` is unknown .label = unknown prefix .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 +lint_self_type_conversion = this conversion is useless `{$source}` to `{$target}` + lint_shadowed_into_iter = this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5f6e7fb314d9f..baf689fac6dbb 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -66,7 +66,7 @@ use crate::lints::{ BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, InvalidAsmLabel, + BuiltinWhileTrue, InvalidAsmLabel, SelfTypeConversionDiag, }; use crate::nonstandard_style::{method_context, MethodLateContext}; use crate::{ @@ -1604,6 +1604,7 @@ declare_lint_pass!( SoftLints => [ WHILE_TRUE, NON_SHORTHAND_FIELD_PATTERNS, + SELF_TYPE_CONVERSION, UNSAFE_CODE, MISSING_DOCS, MISSING_COPY_IMPLEMENTATIONS, @@ -3064,3 +3065,100 @@ impl EarlyLintPass for SpecialModuleName { } } } + +declare_lint! { + /// The `self_type_conversion` lint detects when a call to `.into()` does not have any effect. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// fn main() { + /// let () = ().into(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + pub SELF_TYPE_CONVERSION, + Deny, + "", +} + +pub struct SelfTypeConversion<'tcx> { + ignored_types: Vec>, +} + +impl_lint_pass!(SelfTypeConversion<'_> => [SELF_TYPE_CONVERSION]); + +impl SelfTypeConversion<'_> { + pub fn new() -> Self { + Self { ignored_types: vec![] } + } +} + +impl<'tcx> LateLintPass<'tcx> for SelfTypeConversion<'tcx> { + fn check_item_post(&mut self, cx: &LateContext<'tcx>, item: &hir::Item<'_>) { + let hir::ItemKind::Use(path, kind) = item.kind else { return }; + tracing::info!("{:#?}", item); + tracing::info!(?path, ?kind); + for res in &path.res { + let Res::Def(DefKind::TyAlias, def_id) = res else { continue }; + let ty = cx.tcx.type_of(def_id).instantiate_identity(); + let name = cx.tcx.item_name(*def_id); + // println!("{ty:?} {name:?}"); + self.ignored_types.push(ty); + for stripped in cx.tcx.stripped_cfg_items(def_id.krate) { + if stripped.name.name == name { + tracing::info!("{name:#?}"); + } + } + } + } + + fn check_expr_post(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { + let hir::ExprKind::MethodCall(_segment, rcvr, args, _) = expr.kind else { return }; + if !args.is_empty() { + tracing::info!("non-empty args"); + return; + } + let ty = cx.typeck_results().expr_ty(expr); + let rcvr_ty = cx.typeck_results().expr_ty(rcvr); + tracing::info!(?ty, ?rcvr_ty); + + if ty != rcvr_ty { + tracing::info!("different types"); + return; + } + if self.ignored_types.contains(&rcvr_ty) { + return; + } + let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else { + tracing::info!("no type dependent def id"); + return; + }; + tracing::info!(?def_id); + if Some(def_id) != cx.tcx.get_diagnostic_item(sym::into_fn) { + tracing::info!("not into_fn {:?}", cx.tcx.get_diagnostic_item(sym::into_fn)); + return; + } + tracing::info!(?def_id); + tracing::info!(?expr); + if expr.span.macro_backtrace().next().is_some() { + return; + } + if cx.tcx.sess.source_map().span_to_embeddable_string(expr.span).contains("symbolize/gimli") + { + // HACK + return; + } + // println!("{:#?}", self.ignored_types); + cx.emit_span_lint( + SELF_TYPE_CONVERSION, + expr.span, + SelfTypeConversionDiag { source: rcvr_ty, target: ty }, + ); + // bug!("asdf"); + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4f3933d461bbd..f5ef8beb9c930 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -185,7 +185,7 @@ early_lint_methods!( late_lint_methods!( declare_combined_late_lint_pass, [ - BuiltinCombinedModuleLateLintPass, + BuiltinCombinedModuleLateLintPass<'tcx>, [ ForLoopsOverFallibles: ForLoopsOverFallibles, DerefIntoDynSupertrait: DerefIntoDynSupertrait, @@ -203,6 +203,7 @@ late_lint_methods!( UnitBindings: UnitBindings, NonUpperCaseGlobals: NonUpperCaseGlobals, NonShorthandFieldPatterns: NonShorthandFieldPatterns, + SelfTypeConversion<'tcx>: SelfTypeConversion::new(), UnusedAllocation: UnusedAllocation, // Depends on types used in type definitions MissingCopyImplementations: MissingCopyImplementations, @@ -268,6 +269,7 @@ fn register_builtins(store: &mut LintStore) { store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); store.register_lints(&foreign_modules::get_lints()); + store.register_late_pass(move |_tcx| Box::new(SelfTypeConversion::new())); add_lint_group!( "nonstandard_style", NON_CAMEL_CASE_TYPES, @@ -298,6 +300,7 @@ fn register_builtins(store: &mut LintStore) { UNUSED_PARENS, UNUSED_BRACES, REDUNDANT_SEMICOLONS, + // SELF_TYPE_CONVERSION, MAP_UNIT_FN ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 03962d796f4e2..cd728f7e35912 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -72,6 +72,13 @@ pub struct BuiltinNonShorthandFieldPatterns { pub prefix: &'static str, } +#[derive(LintDiagnostic)] +#[diag(lint_self_type_conversion)] +pub struct SelfTypeConversionDiag<'t> { + pub source: Ty<'t>, + pub target: Ty<'t>, +} + #[derive(LintDiagnostic)] pub enum BuiltinUnsafe { #[diag(lint_builtin_allow_internal_unsafe)] diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index bf16e3b7d150f..a8772c187b988 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -93,13 +93,13 @@ macro_rules! expand_combined_late_lint_pass_methods { /// runtime. #[macro_export] macro_rules! declare_combined_late_lint_pass { - ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( + ([$v:vis $name:ident$(<$lt:lifetime>)?, [$($pass:ident$(<$inner_lt:lifetime>)?: $constructor:expr,)*]], $methods:tt) => ( #[allow(non_snake_case)] - $v struct $name { - $($pass: $pass,)* + $v struct $name$(<$lt>)? { + $($pass: $pass$(<$inner_lt>)?,)* } - impl $name { + impl$(<$lt>)? $name$(<$lt>)? { $v fn new() -> Self { Self { $($pass: $constructor,)* @@ -113,12 +113,12 @@ macro_rules! declare_combined_late_lint_pass { } } - impl<'tcx> $crate::LateLintPass<'tcx> for $name { + impl<'tcx> $crate::LateLintPass<'tcx> for $name$(<$lt>)? { $crate::expand_combined_late_lint_pass_methods!([$($pass),*], $methods); } #[allow(rustc::lint_pass_impl_without_macro)] - impl $crate::LintPass for $name { + impl$(<$lt>)? $crate::LintPass for $name$(<$lt>)? { fn name(&self) -> &'static str { panic!() } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index e373292741b90..744f6b16ef4c1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -384,7 +384,7 @@ impl<'tcx> Const<'tcx> { Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c)) } Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)), - Err(err) => Err(Either::Right(err.into())), + Err(err) => Err(Either::Right(err)), } } ConstKind::Value(ty, val) => Ok((ty, val)), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 319fb7ef03bb3..4fc4e649ae7b1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1526,7 +1526,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let precedence = |binop: rustc_middle::mir::BinOp| { use rustc_ast::util::parser::AssocOp; - AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence() + AssocOp::from_ast_binop(binop.to_hir_binop()).precedence() }; let op_precedence = precedence(op); let formatted_op = op.to_hir_binop().as_str(); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 47820e93c23d2..cca296f3f4287 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1586,7 +1586,7 @@ impl<'a> Parser<'a> { (thin_vec![], Recovered::Yes(guar)) } }; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { let body = match this.parse_tuple_struct_body() { Ok(body) => body, @@ -1670,7 +1670,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { @@ -1682,7 +1682,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(Delimiter::Parenthesis) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID); @@ -1711,14 +1711,14 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "union", class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else { let token_str = super::token_descr(&self.token); let msg = format!("expected `where` or `{{` after union name, found {token_str}"); diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index cb8e8d309887b..678b34f25f30a 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1186,8 +1186,7 @@ fn string_to_tts_1() { token::Ident(sym::i32, IdentIsRaw::No), sp(8, 11), ), - ]) - .into(), + ]), ), TokenTree::Delimited( DelimSpan::from_pair(sp(13, 14), sp(18, 19)), @@ -1203,8 +1202,7 @@ fn string_to_tts_1() { ), // `Alone` because the `;` is followed by whitespace. TokenTree::token_alone(token::Semi, sp(16, 17)), - ]) - .into(), + ]), ), ]); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2e94492f8c23..6b204952e2996 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1045,6 +1045,7 @@ symbols! { integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, into_async_iter_into_iter, + into_fn, into_future, into_iter, intra_doc_pointers, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 3a606f244e37a..c3a1643c1f49e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -382,7 +382,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let consts = [ start.unwrap_or(self.tcx.consts.unit), end.unwrap_or(self.tcx.consts.unit), - ty::Const::from_bool(self.tcx, include_end).into(), + ty::Const::from_bool(self.tcx, include_end), ]; // HACK: Represent as tuple until we have something better. // HACK: constants are used in arrays, even if the types don't match. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 568214fe02298..63626988baa88 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -406,7 +406,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( debug!("opt_normalize_projection_type: found error"); let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); - return Ok(Some(result.value.into())); + return Ok(Some(result.value)); } } @@ -476,7 +476,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( } let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); - Ok(Some(result.value.into())) + Ok(Some(result.value)) } } } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bdee06154faec..5937b375e104b 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1714,7 +1714,7 @@ impl Rc { /// let x: Rc<&str> = Rc::new("Hello, world!"); /// { /// let s = String::from("Oh, no!"); - /// let mut y: Rc<&str> = x.clone().into(); + /// let mut y: Rc<&str> = x.clone(); /// unsafe { /// // this is Undefined Behavior, because x's inner type /// // is &'long str, not &'short str diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2c0d19b0ada09..125ec1f8817aa 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2408,7 +2408,7 @@ impl Arc { /// let x: Arc<&str> = Arc::new("Hello, world!"); /// { /// let s = String::from("Oh, no!"); - /// let mut y: Arc<&str> = x.clone().into(); + /// let mut y: Arc<&str> = x.clone(); /// unsafe { /// // this is Undefined Behavior, because x's inner type /// // is &'long str, not &'short str diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 432e55e8c9a4c..c91ef416ff5da 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -445,6 +445,7 @@ pub trait AsMut { #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Converts this type into the (usually inferred) input type. + #[rustc_diagnostic_item = "into_fn"] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn into(self) -> T; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 2d087c03b04b4..fd563b84f3dc5 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -2,7 +2,7 @@ #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] - +#![cfg_attr(not(bootstrap), allow(self_type_conversion))] use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::marker::PhantomData; use crate::mem::ManuallyDrop; diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5552e9ac97753..2c21022740dd1 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -282,6 +282,7 @@ impl Command { // have the drop glue anyway because this code never returns (the // child will either exec() or invoke libc::exit) #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] + #[cfg_attr(not(bootstrap), allow(self_type_conversion))] unsafe fn do_exec( &mut self, stdio: ChildPipes, diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 5333ee146f7d6..ea43a7167f276 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -31,6 +31,7 @@ impl fmt::Debug for CommandEnv { impl CommandEnv { // Capture the current environment with these changes applied + #[cfg_attr(not(bootstrap), allow(self_type_conversion))] pub fn capture(&self) -> BTreeMap { let mut result = BTreeMap::::new(); if !self.clear { diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed index 9b7da85266316..b8a58f5dc71ca 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed @@ -30,7 +30,7 @@ fn main() -> Result<(), ()> { return Ok::<(), ()>(()); Err(())?; Ok::<(), ()>(()); - return Err(().into()); + return Err(()); external! { return Err(())?; } diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs index 68e76d2b6402e..dd5b437aa19af 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs @@ -30,7 +30,7 @@ fn main() -> Result<(), ()> { return Ok::<(), ()>(()); Err(())?; Ok::<(), ()>(()); - return Err(().into()); + return Err(()); external! { return Err(())?; } diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index 82f945c5e89f6..daace024951e1 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -16,12 +16,26 @@ error: useless conversion to the same type: `T` LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` +error: this conversion is useless `T` to `T` + --> tests/ui/useless_conversion.rs:6:5 + | +LL | val.into() + | ^^^^^^^^^^ + | + = note: `#[deny(self_type_conversion)]` on by default + error: useless conversion to the same type: `i32` --> tests/ui/useless_conversion.rs:18:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` +error: this conversion is useless `i32` to `i32` + --> tests/ui/useless_conversion.rs:18:22 + | +LL | let _: i32 = 0i32.into(); + | ^^^^^^^^^^^ + error: useless conversion to the same type: `std::str::Lines<'_>` --> tests/ui/useless_conversion.rs:48:22 | @@ -58,6 +72,12 @@ error: useless conversion to the same type: `std::string::String` LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` +error: this conversion is useless `std::string::String` to `std::string::String` + --> tests/ui/useless_conversion.rs:132:21 + | +LL | let _: String = "foo".to_string().into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: useless conversion to the same type: `std::string::String` --> tests/ui/useless_conversion.rs:133:21 | @@ -94,6 +114,12 @@ error: useless conversion to the same type: `std::string::String` LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` +error: this conversion is useless `std::string::String` to `std::string::String` + --> tests/ui/useless_conversion.rs:138:21 + | +LL | let _: String = format!("Hello {}", "world").into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: useless conversion to the same type: `i32` --> tests/ui/useless_conversion.rs:143:13 | @@ -106,6 +132,12 @@ error: useless conversion to the same type: `Foo<'a'>` LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` +error: this conversion is useless `Foo<'a'>` to `Foo<'a'>` + --> tests/ui/useless_conversion.rs:149:23 + | +LL | let _: Foo<'a'> = s2.into(); + | ^^^^^^^^^ + error: useless conversion to the same type: `Foo<'a'>` --> tests/ui/useless_conversion.rs:151:13 | @@ -226,5 +258,45 @@ note: this parameter accepts any `IntoIterator`, so you don't need to call `.int LL | J: IntoIterator, | ^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: this conversion is useless `T` to `T` + --> tests/ui/useless_conversion.rs:6:5 + | +LL | val.into() + | ^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: this conversion is useless `i32` to `i32` + --> tests/ui/useless_conversion.rs:18:22 + | +LL | let _: i32 = 0i32.into(); + | ^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: this conversion is useless `std::string::String` to `std::string::String` + --> tests/ui/useless_conversion.rs:132:21 + | +LL | let _: String = "foo".to_string().into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: this conversion is useless `std::string::String` to `std::string::String` + --> tests/ui/useless_conversion.rs:138:21 + | +LL | let _: String = format!("Hello {}", "world").into(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: this conversion is useless `Foo<'a'>` to `Foo<'a'>` + --> tests/ui/useless_conversion.rs:149:23 + | +LL | let _: Foo<'a'> = s2.into(); + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 38 previous errors diff --git a/tests/rustdoc-ui/error-in-impl-trait/realistic-async.rs b/tests/rustdoc-ui/error-in-impl-trait/realistic-async.rs index 6c53c2912e1eb..b80ca3d194b64 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/realistic-async.rs +++ b/tests/rustdoc-ui/error-in-impl-trait/realistic-async.rs @@ -23,6 +23,7 @@ mod unix { #[cfg(any(unix, doc))] use unix::*; +#[cfg(not(doc))] // temporary hack in order to run crater with the deny-by-default lint async fn bar() { ().foo() } diff --git a/tests/rustdoc-ui/issues/issue-83883-describe-lints.stdout b/tests/rustdoc-ui/issues/issue-83883-describe-lints.stdout index 6021bce69397b..c28b1202f31e1 100644 --- a/tests/rustdoc-ui/issues/issue-83883-describe-lints.stdout +++ b/tests/rustdoc-ui/issues/issue-83883-describe-lints.stdout @@ -8,6 +8,7 @@ Available lint options: Lint checks provided by rustc: + $NAMES $LEVELS $MEANINGS self-type-conversion deny $NAMES $LEVELS $MEANINGS Lint groups provided by rustc: diff --git a/tests/ui/deriving/auxiliary/another-proc-macro.rs b/tests/ui/deriving/auxiliary/another-proc-macro.rs index a05175c9de926..29b531677dd49 100644 --- a/tests/ui/deriving/auxiliary/another-proc-macro.rs +++ b/tests/ui/deriving/auxiliary/another-proc-macro.rs @@ -3,6 +3,7 @@ #![crate_type = "proc-macro"] #![feature(proc_macro_quote)] +#![allow(self_type_conversion)] extern crate proc_macro; diff --git a/tests/ui/macros/macro-or-patterns-back-compat.fixed b/tests/ui/macros/macro-or-patterns-back-compat.fixed index c16190c399aef..ac541656364fe 100644 --- a/tests/ui/macros/macro-or-patterns-back-compat.fixed +++ b/tests/ui/macros/macro-or-patterns-back-compat.fixed @@ -2,7 +2,7 @@ //@ aux-build:or-pattern.rs #![deny(rust_2021_incompatible_or_patterns)] -#![allow(unused_macros)] +#![allow(unused_macros, self_type_conversion)] #[macro_use] extern crate or_pattern; diff --git a/tests/ui/macros/macro-or-patterns-back-compat.rs b/tests/ui/macros/macro-or-patterns-back-compat.rs index ef0ffb99c1a62..460840d807192 100644 --- a/tests/ui/macros/macro-or-patterns-back-compat.rs +++ b/tests/ui/macros/macro-or-patterns-back-compat.rs @@ -2,7 +2,7 @@ //@ aux-build:or-pattern.rs #![deny(rust_2021_incompatible_or_patterns)] -#![allow(unused_macros)] +#![allow(unused_macros, self_type_conversion)] #[macro_use] extern crate or_pattern; diff --git a/tests/ui/macros/macro-pat-pattern-followed-by-or.rs b/tests/ui/macros/macro-pat-pattern-followed-by-or.rs index d584e919a2a00..76a0241d22069 100644 --- a/tests/ui/macros/macro-pat-pattern-followed-by-or.rs +++ b/tests/ui/macros/macro-pat-pattern-followed-by-or.rs @@ -1,5 +1,5 @@ //@ run-pass -#![allow(unused_macros)] +#![allow(unused_macros, self_type_conversion)] macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok