Skip to content

Commit 1dee616

Browse files
authored
Suggest naming types before using explicit type names (#14996)
`missing_transmute_annotations` will suggest naming the origin and destination types if they do not have explicit names already. changelog: [`missing_transmute_annotations`]: suggest giving origin and destination types a name in order to ascribe the `transmute` call Fixes rust-lang/rust-clippy#14984
2 parents 0126bc9 + a7ff2b0 commit 1dee616

File tree

4 files changed

+113
-9
lines changed

4 files changed

+113
-9
lines changed

clippy_lints/src/transmute/missing_transmute_annotations.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
1+
use std::borrow::Cow;
2+
3+
use clippy_utils::diagnostics::span_lint_and_then;
4+
use clippy_utils::source::{HasSession, SpanRangeExt as _};
25
use rustc_errors::Applicability;
3-
use rustc_hir::{GenericArg, HirId, LetStmt, Node, Path, TyKind};
6+
use rustc_hir::{Expr, GenericArg, HirId, LetStmt, Node, Path, TyKind};
47
use rustc_lint::LateContext;
5-
use rustc_middle::ty::Ty;
8+
use rustc_middle::ty::{self, Ty};
9+
use rustc_span::Span;
610

711
use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS;
812

@@ -38,6 +42,7 @@ fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool {
3842
pub(super) fn check<'tcx>(
3943
cx: &LateContext<'tcx>,
4044
path: &Path<'tcx>,
45+
arg: &Expr<'tcx>,
4146
from_ty: Ty<'tcx>,
4247
to_ty: Ty<'tcx>,
4348
expr_hir_id: HirId,
@@ -68,14 +73,48 @@ pub(super) fn check<'tcx>(
6873
} else if is_function_block(cx, expr_hir_id) {
6974
return false;
7075
}
71-
span_lint_and_sugg(
76+
let span = last.ident.span.with_hi(path.span.hi());
77+
span_lint_and_then(
7278
cx,
7379
MISSING_TRANSMUTE_ANNOTATIONS,
74-
last.ident.span.with_hi(path.span.hi()),
80+
span,
7581
"transmute used without annotations",
76-
"consider adding missing annotations",
77-
format!("{}::<{from_ty}, {to_ty}>", last.ident),
78-
Applicability::MaybeIncorrect,
82+
|diag| {
83+
let from_ty_no_name = ty_cannot_be_named(from_ty);
84+
let to_ty_no_name = ty_cannot_be_named(to_ty);
85+
if from_ty_no_name || to_ty_no_name {
86+
let to_name = match (from_ty_no_name, to_ty_no_name) {
87+
(true, false) => maybe_name_by_expr(cx, arg.span, "the origin type"),
88+
(false, true) => "the destination type".into(),
89+
_ => "the source and destination types".into(),
90+
};
91+
diag.help(format!(
92+
"consider giving {to_name} a name, and adding missing type annotations"
93+
));
94+
} else {
95+
diag.span_suggestion(
96+
span,
97+
"consider adding missing annotations",
98+
format!("{}::<{from_ty}, {to_ty}>", last.ident),
99+
Applicability::MaybeIncorrect,
100+
);
101+
}
102+
},
79103
);
80104
true
81105
}
106+
107+
fn ty_cannot_be_named(ty: Ty<'_>) -> bool {
108+
matches!(
109+
ty.kind(),
110+
ty::Alias(ty::AliasTyKind::Opaque | ty::AliasTyKind::Inherent, _)
111+
)
112+
}
113+
114+
fn maybe_name_by_expr<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow<'a, str> {
115+
span.with_source_text(sess, |name| {
116+
(name.len() + 9 < default.len()).then_some(format!("`{name}`'s type").into())
117+
})
118+
.flatten()
119+
.unwrap_or(default.into())
120+
}

clippy_lints/src/transmute/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
520520
| transmuting_null::check(cx, e, arg, to_ty)
521521
| transmute_null_to_fn::check(cx, e, arg, to_ty)
522522
| transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, self.msrv)
523-
| missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id)
523+
| missing_transmute_annotations::check(cx, path, arg, from_ty, to_ty, e.hir_id)
524524
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
525525
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, self.msrv)
526526
| transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@no-rustfix
2+
3+
fn issue14984() {
4+
async fn e() {}
5+
async fn x() -> u32 {
6+
0
7+
}
8+
async fn y() -> f32 {
9+
0.0
10+
};
11+
let mut yy = unsafe { std::ptr::read(&y()) };
12+
yy = unsafe { std::mem::transmute(std::ptr::read(&x())) };
13+
//~^ missing_transmute_annotations
14+
15+
let mut zz = 0u8;
16+
zz = unsafe { std::mem::transmute(std::ptr::read(&x())) };
17+
//~^ missing_transmute_annotations
18+
19+
yy = unsafe { std::mem::transmute(zz) };
20+
//~^ missing_transmute_annotations
21+
22+
fn a() -> impl Sized {
23+
0u32
24+
}
25+
26+
let mut b: f32 = 0.0;
27+
b = unsafe { std::mem::transmute(a()) };
28+
//~^ missing_transmute_annotations
29+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error: transmute used without annotations
2+
--> tests/ui/missing_transmute_annotations_unfixable.rs:12:29
3+
|
4+
LL | yy = unsafe { std::mem::transmute(std::ptr::read(&x())) };
5+
| ^^^^^^^^^
6+
|
7+
= help: consider giving the source and destination types a name, and adding missing type annotations
8+
= note: `-D clippy::missing-transmute-annotations` implied by `-D warnings`
9+
= help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]`
10+
11+
error: transmute used without annotations
12+
--> tests/ui/missing_transmute_annotations_unfixable.rs:16:29
13+
|
14+
LL | zz = unsafe { std::mem::transmute(std::ptr::read(&x())) };
15+
| ^^^^^^^^^
16+
|
17+
= help: consider giving the origin type a name, and adding missing type annotations
18+
19+
error: transmute used without annotations
20+
--> tests/ui/missing_transmute_annotations_unfixable.rs:19:29
21+
|
22+
LL | yy = unsafe { std::mem::transmute(zz) };
23+
| ^^^^^^^^^
24+
|
25+
= help: consider giving the destination type a name, and adding missing type annotations
26+
27+
error: transmute used without annotations
28+
--> tests/ui/missing_transmute_annotations_unfixable.rs:27:28
29+
|
30+
LL | b = unsafe { std::mem::transmute(a()) };
31+
| ^^^^^^^^^
32+
|
33+
= help: consider giving `a()`'s type a name, and adding missing type annotations
34+
35+
error: aborting due to 4 previous errors
36+

0 commit comments

Comments
 (0)