Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 622c05b

Browse files
committed
Auto merge of rust-lang#129249 - estebank:useless-into, r=<try>
[Experimental] `<T as Into<T>>::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.
2 parents 6de928d + 2aaca93 commit 622c05b

File tree

27 files changed

+214
-35
lines changed

27 files changed

+214
-35
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,7 +3464,7 @@ impl From<ForeignItemKind> for ItemKind {
34643464
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
34653465
match foreign_item_kind {
34663466
ForeignItemKind::Static(box static_foreign_item) => {
3467-
ItemKind::Static(Box::new(static_foreign_item.into()))
3467+
ItemKind::Static(Box::new(static_foreign_item))
34683468
}
34693469
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
34703470
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
@@ -3478,9 +3478,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
34783478

34793479
fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
34803480
Ok(match item_kind {
3481-
ItemKind::Static(box static_item) => {
3482-
ForeignItemKind::Static(Box::new(static_item.into()))
3483-
}
3481+
ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)),
34843482
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
34853483
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
34863484
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
7878
ecx.push_stack_frame_raw(
7979
cid.instance,
8080
body,
81-
&ret.clone().into(),
81+
&ret.clone(),
8282
StackPopCleanup::Root { cleanup: false },
8383
)?;
8484
ecx.storage_live_for_always_live_locals()?;

compiler/rustc_const_eval/src/interpret/call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
854854
(Abi::Rust, fn_abi),
855855
&[FnArg::Copy(arg.into())],
856856
false,
857-
&ret.into(),
857+
&ret,
858858
Some(target),
859859
unwind,
860860
)

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2533,7 +2533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25332533
other_generic_param.name.ident() == generic_param.name.ident()
25342534
},
25352535
) {
2536-
idxs_matched.push(other_idx.into());
2536+
idxs_matched.push(other_idx);
25372537
}
25382538

25392539
if idxs_matched.is_empty() {

compiler/rustc_lint/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ lint_builtin_no_mangle_static = declaration of a `no_mangle` static
129129
lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant
130130
.suggestion = use shorthand field pattern
131131
132+
lint_self_type_conversion = this conversion is useless `{$source}` to `{$target}`
133+
132134
lint_builtin_overridden_symbol_name =
133135
the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
134136

compiler/rustc_lint/src/builtin.rs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use crate::lints::{
6666
BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
6767
BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
6868
BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
69-
BuiltinWhileTrue, InvalidAsmLabel,
69+
BuiltinWhileTrue, InvalidAsmLabel, SelfTypeConversionDiag,
7070
};
7171
use crate::nonstandard_style::{method_context, MethodLateContext};
7272
use crate::{
@@ -1604,6 +1604,7 @@ declare_lint_pass!(
16041604
SoftLints => [
16051605
WHILE_TRUE,
16061606
NON_SHORTHAND_FIELD_PATTERNS,
1607+
SELF_TYPE_CONVERSION,
16071608
UNSAFE_CODE,
16081609
MISSING_DOCS,
16091610
MISSING_COPY_IMPLEMENTATIONS,
@@ -3064,3 +3065,95 @@ impl EarlyLintPass for SpecialModuleName {
30643065
}
30653066
}
30663067
}
3068+
3069+
declare_lint! {
3070+
/// The `self_type_conversion` lint detects when a call to `.into()` does not have any effect.
3071+
///
3072+
/// ### Example
3073+
///
3074+
/// ```rust,compile_fail
3075+
/// fn main() {
3076+
/// let () = ().into();
3077+
/// }
3078+
/// ```
3079+
///
3080+
/// {{produces}}
3081+
///
3082+
/// ### Explanation
3083+
///
3084+
pub SELF_TYPE_CONVERSION,
3085+
Deny,
3086+
"",
3087+
}
3088+
3089+
pub struct SelfTypeConversion<'tcx> {
3090+
ignored_types: Vec<Ty<'tcx>>,
3091+
}
3092+
3093+
impl_lint_pass!(SelfTypeConversion<'_> => [SELF_TYPE_CONVERSION]);
3094+
3095+
impl SelfTypeConversion<'_> {
3096+
pub fn new() -> Self {
3097+
Self { ignored_types: vec![] }
3098+
}
3099+
}
3100+
3101+
impl<'tcx> LateLintPass<'tcx> for SelfTypeConversion<'tcx> {
3102+
fn check_item_post(&mut self, cx: &LateContext<'tcx>, item: &hir::Item<'_>) {
3103+
let hir::ItemKind::Use(path, kind) = item.kind else { return };
3104+
tracing::info!("{:#?}", item);
3105+
tracing::info!(?path, ?kind);
3106+
for res in &path.res {
3107+
let Res::Def(DefKind::TyAlias, def_id) = res else { continue };
3108+
let ty = cx.tcx.type_of(def_id).instantiate_identity();
3109+
let name = cx.tcx.item_name(*def_id);
3110+
// println!("{ty:?} {name:?}");
3111+
self.ignored_types.push(ty);
3112+
for stripped in cx.tcx.stripped_cfg_items(def_id.krate) {
3113+
if stripped.name.name == name {
3114+
tracing::info!("{name:#?}");
3115+
}
3116+
}
3117+
}
3118+
}
3119+
3120+
fn check_expr_post(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
3121+
let hir::ExprKind::MethodCall(_segment, rcvr, args, _) = expr.kind else { return };
3122+
if !args.is_empty() {
3123+
tracing::info!("non-empty args");
3124+
return;
3125+
}
3126+
let ty = cx.typeck_results().expr_ty(expr);
3127+
let rcvr_ty = cx.typeck_results().expr_ty(rcvr);
3128+
tracing::info!(?ty, ?rcvr_ty);
3129+
3130+
if ty != rcvr_ty {
3131+
tracing::info!("different types");
3132+
return;
3133+
}
3134+
if self.ignored_types.contains(&rcvr_ty) {
3135+
return;
3136+
}
3137+
let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
3138+
tracing::info!("no type dependent def id");
3139+
return;
3140+
};
3141+
tracing::info!(?def_id);
3142+
if Some(def_id) != cx.tcx.get_diagnostic_item(sym::into_fn) {
3143+
tracing::info!("not into_fn {:?}", cx.tcx.get_diagnostic_item(sym::into_fn));
3144+
return;
3145+
}
3146+
tracing::info!(?def_id);
3147+
tracing::info!(?expr);
3148+
if expr.span.macro_backtrace().next().is_some() {
3149+
return;
3150+
}
3151+
// println!("{:#?}", self.ignored_types);
3152+
cx.emit_span_lint(
3153+
SELF_TYPE_CONVERSION,
3154+
expr.span,
3155+
SelfTypeConversionDiag { source: rcvr_ty, target: ty },
3156+
);
3157+
// bug!("asdf");
3158+
}
3159+
}

compiler/rustc_lint/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ early_lint_methods!(
185185
late_lint_methods!(
186186
declare_combined_late_lint_pass,
187187
[
188-
BuiltinCombinedModuleLateLintPass,
188+
BuiltinCombinedModuleLateLintPass<'tcx>,
189189
[
190190
ForLoopsOverFallibles: ForLoopsOverFallibles,
191191
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
@@ -203,6 +203,7 @@ late_lint_methods!(
203203
UnitBindings: UnitBindings,
204204
NonUpperCaseGlobals: NonUpperCaseGlobals,
205205
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
206+
SelfTypeConversion<'tcx>: SelfTypeConversion::new(),
206207
UnusedAllocation: UnusedAllocation,
207208
// Depends on types used in type definitions
208209
MissingCopyImplementations: MissingCopyImplementations,
@@ -268,6 +269,7 @@ fn register_builtins(store: &mut LintStore) {
268269
store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
269270
store.register_lints(&foreign_modules::get_lints());
270271

272+
store.register_late_pass(move |_tcx| Box::new(SelfTypeConversion::new()));
271273
add_lint_group!(
272274
"nonstandard_style",
273275
NON_CAMEL_CASE_TYPES,
@@ -298,6 +300,7 @@ fn register_builtins(store: &mut LintStore) {
298300
UNUSED_PARENS,
299301
UNUSED_BRACES,
300302
REDUNDANT_SEMICOLONS,
303+
// SELF_TYPE_CONVERSION,
301304
MAP_UNIT_FN
302305
);
303306

compiler/rustc_lint/src/lints.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ pub struct BuiltinNonShorthandFieldPatterns {
7272
pub prefix: &'static str,
7373
}
7474

75+
#[derive(LintDiagnostic)]
76+
#[diag(lint_self_type_conversion)]
77+
pub struct SelfTypeConversionDiag<'t> {
78+
pub source: Ty<'t>,
79+
pub target: Ty<'t>,
80+
}
81+
7582
#[derive(LintDiagnostic)]
7683
pub enum BuiltinUnsafe {
7784
#[diag(lint_builtin_allow_internal_unsafe)]

compiler/rustc_lint/src/passes.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ macro_rules! expand_combined_late_lint_pass_methods {
9393
/// runtime.
9494
#[macro_export]
9595
macro_rules! declare_combined_late_lint_pass {
96-
([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
96+
([$v:vis $name:ident$(<$lt:lifetime>)?, [$($pass:ident$(<$inner_lt:lifetime>)?: $constructor:expr,)*]], $methods:tt) => (
9797
#[allow(non_snake_case)]
98-
$v struct $name {
99-
$($pass: $pass,)*
98+
$v struct $name$(<$lt>)? {
99+
$($pass: $pass$(<$inner_lt>)?,)*
100100
}
101101

102-
impl $name {
102+
impl$(<$lt>)? $name$(<$lt>)? {
103103
$v fn new() -> Self {
104104
Self {
105105
$($pass: $constructor,)*
@@ -113,12 +113,12 @@ macro_rules! declare_combined_late_lint_pass {
113113
}
114114
}
115115

116-
impl<'tcx> $crate::LateLintPass<'tcx> for $name {
116+
impl<'tcx> $crate::LateLintPass<'tcx> for $name$(<$lt>)? {
117117
$crate::expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
118118
}
119119

120120
#[allow(rustc::lint_pass_impl_without_macro)]
121-
impl $crate::LintPass for $name {
121+
impl$(<$lt>)? $crate::LintPass for $name$(<$lt>)? {
122122
fn name(&self) -> &'static str {
123123
panic!()
124124
}

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl<'tcx> Const<'tcx> {
384384
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
385385
}
386386
Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
387-
Err(err) => Err(Either::Right(err.into())),
387+
Err(err) => Err(Either::Right(err)),
388388
}
389389
}
390390
ConstKind::Value(ty, val) => Ok((ty, val)),

0 commit comments

Comments
 (0)