Skip to content

Commit 9fe0b28

Browse files
committed
Simplify implementation.
1 parent a3c878f commit 9fe0b28

File tree

1 file changed

+46
-44
lines changed

1 file changed

+46
-44
lines changed

compiler/rustc_hir_typeck/src/intrinsicck.rs

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hir as hir;
77
use rustc_index::Idx;
88
use rustc_middle::bug;
99
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
10-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
10+
use rustc_middle::ty::{self, Ty, TyCtxt};
1111
use rustc_span::def_id::LocalDefId;
1212
use tracing::trace;
1313

@@ -38,58 +38,86 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
3838
ty
3939
}
4040

41+
/// Try to display a sensible error with as much information as possible.
42+
fn skeleton_string<'tcx>(
43+
ty: Ty<'tcx>,
44+
sk: Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>>,
45+
) -> String {
46+
match sk {
47+
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
48+
Ok(SizeSkeleton::Known(size, _)) => {
49+
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
50+
format!("{v} bits")
51+
} else {
52+
// `u128` should definitely be able to hold the size of different architectures
53+
// larger sizes should be reported as error `are too big for the target architecture`
54+
// otherwise we have a bug somewhere
55+
bug!("{:?} overflow for u128", size)
56+
}
57+
}
58+
Ok(SizeSkeleton::Generic(size)) => {
59+
format!("generic size {size}")
60+
}
61+
Err(LayoutError::TooGeneric(bad)) => {
62+
if *bad == ty {
63+
"this type does not have a fixed size".to_owned()
64+
} else {
65+
format!("size can vary because of {bad}")
66+
}
67+
}
68+
Err(err) => err.to_string(),
69+
}
70+
}
71+
4172
fn check_transmute<'tcx>(
4273
tcx: TyCtxt<'tcx>,
4374
typing_env: ty::TypingEnv<'tcx>,
4475
from: Ty<'tcx>,
4576
to: Ty<'tcx>,
4677
hir_id: HirId,
4778
) {
48-
let dl = &tcx.data_layout;
49-
let span = tcx.hir_span(hir_id);
79+
let span = || tcx.hir_span(hir_id);
5080
let normalize = |ty| {
5181
if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) {
5282
ty
5383
} else {
5484
Ty::new_error_with_message(
5585
tcx,
56-
span,
86+
span(),
5787
format!("tried to normalize non-wf type {ty:#?} in check_transmute"),
5888
)
5989
}
6090
};
91+
6192
let from = normalize(from);
6293
let to = normalize(to);
6394
trace!(?from, ?to);
64-
if from.has_non_region_infer() || to.has_non_region_infer() {
65-
// Note: this path is currently not reached in any test, so any
66-
// example that triggers this would be worth minimizing and
67-
// converting into a test.
68-
tcx.sess.dcx().span_bug(span, "argument to transmute has inference variables");
69-
}
95+
7096
// Transmutes that are only changing lifetimes are always ok.
7197
if from == to {
7298
return;
7399
}
74100

75-
let skel = |ty| SizeSkeleton::compute(ty, tcx, typing_env);
76-
let sk_from = skel(from);
77-
let sk_to = skel(to);
101+
let sk_from = SizeSkeleton::compute(from, tcx, typing_env);
102+
let sk_to = SizeSkeleton::compute(to, tcx, typing_env);
78103
trace!(?sk_from, ?sk_to);
79104

80105
// Check for same size using the skeletons.
81-
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
106+
if let Ok(sk_from) = sk_from
107+
&& let Ok(sk_to) = sk_to
108+
{
82109
if sk_from.same_size(sk_to) {
83110
return;
84111
}
85112

86113
// Special-case transmuting from `typeof(function)` and
87114
// `Option<typeof(function)>` to present a clearer error.
88115
let from = unpack_option_like(tcx, from);
89-
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
90-
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
116+
if let ty::FnDef(..) = from.kind()
117+
&& let SizeSkeleton::Known(size_to, _) = sk_to
118+
&& size_to == Pointer(tcx.data_layout.instruction_address_space).size(&tcx)
91119
{
92-
struct_span_code_err!(tcx.sess.dcx(), span, E0591, "can't transmute zero-sized type")
120+
struct_span_code_err!(tcx.sess.dcx(), span(), E0591, "can't transmute zero-sized type")
93121
.with_note(format!("source type: {from}"))
94122
.with_note(format!("target type: {to}"))
95123
.with_help("cast with `as` to a pointer instead")
@@ -98,35 +126,9 @@ fn check_transmute<'tcx>(
98126
}
99127
}
100128

101-
// Try to display a sensible error with as much information as possible.
102-
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
103-
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
104-
Ok(SizeSkeleton::Known(size, _)) => {
105-
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
106-
format!("{v} bits")
107-
} else {
108-
// `u128` should definitely be able to hold the size of different architectures
109-
// larger sizes should be reported as error `are too big for the target architecture`
110-
// otherwise we have a bug somewhere
111-
bug!("{:?} overflow for u128", size)
112-
}
113-
}
114-
Ok(SizeSkeleton::Generic(size)) => {
115-
format!("generic size {size}")
116-
}
117-
Err(LayoutError::TooGeneric(bad)) => {
118-
if *bad == ty {
119-
"this type does not have a fixed size".to_owned()
120-
} else {
121-
format!("size can vary because of {bad}")
122-
}
123-
}
124-
Err(err) => err.to_string(),
125-
};
126-
127129
let mut err = struct_span_code_err!(
128130
tcx.sess.dcx(),
129-
span,
131+
span(),
130132
E0512,
131133
"cannot transmute between types of different sizes, or dependently-sized types"
132134
);

0 commit comments

Comments
 (0)