mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 03:03:40 +00:00
Auto merge of #9287 - Jarcho:trans_undefined, r=xFrednet
`transmute_undefined_repr` fix changelog: Don't lint `transmute_undefined_repr` when the the first field of a `repr(C)` type is compatible with the other type
This commit is contained in:
commit
84fb7e0395
@ -5,9 +5,9 @@ use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[expect(clippy::too_many_lines)]
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'_>,
|
||||
@ -18,116 +18,89 @@ pub(super) fn check<'tcx>(
|
||||
let mut to_ty = cx.tcx.erase_regions(to_ty_orig);
|
||||
|
||||
while from_ty != to_ty {
|
||||
match reduce_refs(cx, e.span, from_ty, to_ty) {
|
||||
ReducedTys::FromFatPtr {
|
||||
unsized_ty,
|
||||
to_ty: to_sub_ty,
|
||||
} => match reduce_ty(cx, to_sub_ty) {
|
||||
ReducedTy::TypeErasure => break,
|
||||
ReducedTy::UnorderedFields(ty) if is_size_pair(ty) => break,
|
||||
ReducedTy::Ref(to_sub_ty) => {
|
||||
from_ty = unsized_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
_ => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
|
||||
|diag| {
|
||||
if from_ty_orig.peel_refs() != unsized_ty {
|
||||
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
let reduced_tys = reduce_refs(cx, from_ty, to_ty);
|
||||
match (reduce_ty(cx, reduced_tys.from_ty), reduce_ty(cx, reduced_tys.to_ty)) {
|
||||
// Various forms of type erasure.
|
||||
(ReducedTy::TypeErasure { raw_ptr_only: false }, _)
|
||||
| (_, ReducedTy::TypeErasure { raw_ptr_only: false }) => return false,
|
||||
(ReducedTy::TypeErasure { .. }, _) if reduced_tys.from_raw_ptr => return false,
|
||||
(_, ReducedTy::TypeErasure { .. }) if reduced_tys.to_raw_ptr => return false,
|
||||
|
||||
// `Repr(C)` <-> unordered type.
|
||||
// If the first field of the `Repr(C)` type matches then the transmute is ok
|
||||
(ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty))
|
||||
| (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
ReducedTys::ToFatPtr {
|
||||
unsized_ty,
|
||||
from_ty: from_sub_ty,
|
||||
} => match reduce_ty(cx, from_sub_ty) {
|
||||
ReducedTy::TypeErasure => break,
|
||||
ReducedTy::UnorderedFields(ty) if is_size_pair(ty) => break,
|
||||
ReducedTy::Ref(from_sub_ty) => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = unsized_ty;
|
||||
continue;
|
||||
},
|
||||
_ => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute to `{}` which has an undefined layout", to_ty_orig),
|
||||
|diag| {
|
||||
if to_ty_orig.peel_refs() != unsized_ty {
|
||||
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
ReducedTys::ToPtr {
|
||||
from_ty: from_sub_ty,
|
||||
to_ty: to_sub_ty,
|
||||
} => match reduce_ty(cx, from_sub_ty) {
|
||||
ReducedTy::UnorderedFields(from_ty) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
|
||||
|diag| {
|
||||
if from_ty_orig.peel_refs() != from_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
ReducedTy::Ref(from_sub_ty) => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
_ => break,
|
||||
(ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty)))
|
||||
if reduced_tys.from_fat_ptr =>
|
||||
{
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
ReducedTys::FromPtr {
|
||||
from_ty: from_sub_ty,
|
||||
to_ty: to_sub_ty,
|
||||
} => match reduce_ty(cx, to_sub_ty) {
|
||||
ReducedTy::UnorderedFields(to_ty) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute to `{}` which has an undefined layout", to_ty_orig),
|
||||
|diag| {
|
||||
if to_ty_orig.peel_refs() != to_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
ReducedTy::Ref(to_sub_ty) => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
_ => break,
|
||||
|
||||
// ptr <-> ptr
|
||||
(ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty))
|
||||
if matches!(from_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_))
|
||||
&& matches!(to_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_)) =>
|
||||
{
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
ReducedTys::Other {
|
||||
from_ty: from_sub_ty,
|
||||
to_ty: to_sub_ty,
|
||||
} => match (reduce_ty(cx, from_sub_ty), reduce_ty(cx, to_sub_ty)) {
|
||||
(ReducedTy::TypeErasure, _) | (_, ReducedTy::TypeErasure) => return false,
|
||||
(ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
|
||||
let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs))
|
||||
|
||||
// fat ptr <-> (*size, *size)
|
||||
(ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty))
|
||||
if reduced_tys.from_fat_ptr && is_size_pair(to_ty) =>
|
||||
{
|
||||
return false;
|
||||
},
|
||||
(ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_))
|
||||
if reduced_tys.to_fat_ptr && is_size_pair(from_ty) =>
|
||||
{
|
||||
return false;
|
||||
},
|
||||
|
||||
// fat ptr -> some struct | some struct -> fat ptr
|
||||
(ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
|
||||
|diag| {
|
||||
if from_ty_orig.peel_refs() != from_ty.peel_refs() {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute to `{}` which has an undefined layout", to_ty_orig),
|
||||
|diag| {
|
||||
if to_ty_orig.peel_refs() != to_ty.peel_refs() {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
|
||||
(ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
|
||||
let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs))
|
||||
= (from_ty.kind(), to_ty.kind())
|
||||
&& from_def == to_def
|
||||
{
|
||||
@ -138,79 +111,72 @@ pub(super) fn check<'tcx>(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!(
|
||||
"transmute from `{}` to `{}`, both of which have an undefined layout",
|
||||
from_ty_orig, to_ty_orig
|
||||
),
|
||||
|diag| {
|
||||
if let Some(same_adt_did) = same_adt_did {
|
||||
diag.note(&format!(
|
||||
"two instances of the same generic type (`{}`) may have different layouts",
|
||||
cx.tcx.item_name(same_adt_did)
|
||||
));
|
||||
} else {
|
||||
if from_ty_orig.peel_refs() != from_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
|
||||
}
|
||||
if to_ty_orig.peel_refs() != to_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(
|
||||
ReducedTy::UnorderedFields(from_ty),
|
||||
ReducedTy::Other(_) | ReducedTy::OrderedFields(_) | ReducedTy::Ref(_),
|
||||
) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
|
||||
|diag| {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!(
|
||||
"transmute from `{}` to `{}`, both of which have an undefined layout",
|
||||
from_ty_orig, to_ty_orig
|
||||
),
|
||||
|diag| {
|
||||
if let Some(same_adt_did) = same_adt_did {
|
||||
diag.note(&format!(
|
||||
"two instances of the same generic type (`{}`) may have different layouts",
|
||||
cx.tcx.item_name(same_adt_did)
|
||||
));
|
||||
} else {
|
||||
if from_ty_orig.peel_refs() != from_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(
|
||||
ReducedTy::Other(_) | ReducedTy::OrderedFields(_) | ReducedTy::Ref(_),
|
||||
ReducedTy::UnorderedFields(to_ty),
|
||||
) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute into `{}` which has an undefined layout", to_ty_orig),
|
||||
|diag| {
|
||||
if to_ty_orig.peel_refs() != to_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(ReducedTy::Ref(from_sub_ty), ReducedTy::Ref(to_sub_ty)) => {
|
||||
from_ty = from_sub_ty;
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
(
|
||||
ReducedTy::OrderedFields(_) | ReducedTy::Ref(_) | ReducedTy::Other(_) | ReducedTy::Param,
|
||||
ReducedTy::OrderedFields(_) | ReducedTy::Ref(_) | ReducedTy::Other(_) | ReducedTy::Param,
|
||||
)
|
||||
| (
|
||||
ReducedTy::UnorderedFields(_) | ReducedTy::Param,
|
||||
ReducedTy::UnorderedFields(_) | ReducedTy::Param,
|
||||
) => break,
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(
|
||||
ReducedTy::UnorderedFields(from_ty),
|
||||
ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
|
||||
) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
|
||||
|diag| {
|
||||
if from_ty_orig.peel_refs() != from_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(
|
||||
ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
|
||||
ReducedTy::UnorderedFields(to_ty),
|
||||
) => {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
TRANSMUTE_UNDEFINED_REPR,
|
||||
e.span,
|
||||
&format!("transmute into `{}` which has an undefined layout", to_ty_orig),
|
||||
|diag| {
|
||||
if to_ty_orig.peel_refs() != to_ty {
|
||||
diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
|
||||
}
|
||||
},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
(
|
||||
ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
|
||||
ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
|
||||
)
|
||||
| (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => {
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -218,64 +184,64 @@ pub(super) fn check<'tcx>(
|
||||
false
|
||||
}
|
||||
|
||||
enum ReducedTys<'tcx> {
|
||||
FromFatPtr { unsized_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
|
||||
ToFatPtr { unsized_ty: Ty<'tcx>, from_ty: Ty<'tcx> },
|
||||
ToPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
|
||||
FromPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
|
||||
Other { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
|
||||
#[expect(clippy::struct_excessive_bools)]
|
||||
struct ReducedTys<'tcx> {
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
from_raw_ptr: bool,
|
||||
to_raw_ptr: bool,
|
||||
from_fat_ptr: bool,
|
||||
to_fat_ptr: bool,
|
||||
}
|
||||
|
||||
/// Remove references so long as both types are references.
|
||||
fn reduce_refs<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
span: Span,
|
||||
mut from_ty: Ty<'tcx>,
|
||||
mut to_ty: Ty<'tcx>,
|
||||
) -> ReducedTys<'tcx> {
|
||||
loop {
|
||||
return match (from_ty.kind(), to_ty.kind()) {
|
||||
fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> {
|
||||
let mut from_raw_ptr = false;
|
||||
let mut to_raw_ptr = false;
|
||||
let (from_fat_ptr, to_fat_ptr) = loop {
|
||||
break match (from_ty.kind(), to_ty.kind()) {
|
||||
(
|
||||
&(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
|
||||
&(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
|
||||
) => {
|
||||
from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
|
||||
from_ty = from_sub_ty;
|
||||
to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
|
||||
to_ty = to_sub_ty;
|
||||
continue;
|
||||
},
|
||||
(&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _)
|
||||
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
|
||||
if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
|
||||
{
|
||||
ReducedTys::FromFatPtr { unsized_ty, to_ty }
|
||||
(true, false)
|
||||
},
|
||||
(_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
|
||||
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
|
||||
if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
|
||||
{
|
||||
ReducedTys::ToFatPtr { unsized_ty, from_ty }
|
||||
(false, true)
|
||||
},
|
||||
(&(ty::Ref(_, from_ty, _) | ty::RawPtr(TypeAndMut { ty: from_ty, .. })), _) => {
|
||||
ReducedTys::FromPtr { from_ty, to_ty }
|
||||
},
|
||||
(_, &(ty::Ref(_, to_ty, _) | ty::RawPtr(TypeAndMut { ty: to_ty, .. }))) => {
|
||||
ReducedTys::ToPtr { from_ty, to_ty }
|
||||
},
|
||||
_ => ReducedTys::Other { from_ty, to_ty },
|
||||
_ => (false, false),
|
||||
};
|
||||
};
|
||||
ReducedTys {
|
||||
from_ty,
|
||||
to_ty,
|
||||
from_raw_ptr,
|
||||
to_raw_ptr,
|
||||
from_fat_ptr,
|
||||
to_fat_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
enum ReducedTy<'tcx> {
|
||||
/// The type can be used for type erasure.
|
||||
TypeErasure,
|
||||
TypeErasure { raw_ptr_only: bool },
|
||||
/// The type is a struct containing either zero non-zero sized fields, or multiple non-zero
|
||||
/// sized fields with a defined order.
|
||||
OrderedFields(Ty<'tcx>),
|
||||
/// The second value is the first non-zero sized type.
|
||||
OrderedFields(Ty<'tcx>, Option<Ty<'tcx>>),
|
||||
/// The type is a struct containing multiple non-zero sized fields with no defined order.
|
||||
UnorderedFields(Ty<'tcx>),
|
||||
/// The type is a reference to the contained type.
|
||||
Ref(Ty<'tcx>),
|
||||
/// The type is a generic parameter.
|
||||
Param,
|
||||
/// Any other type.
|
||||
Other(Ty<'tcx>),
|
||||
}
|
||||
@ -285,16 +251,18 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
|
||||
loop {
|
||||
ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
|
||||
return match *ty.kind() {
|
||||
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => ReducedTy::TypeErasure,
|
||||
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
|
||||
ReducedTy::TypeErasure { raw_ptr_only: false }
|
||||
},
|
||||
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
|
||||
ty = sub_ty;
|
||||
continue;
|
||||
},
|
||||
ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure,
|
||||
ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false },
|
||||
ty::Tuple(args) => {
|
||||
let mut iter = args.iter();
|
||||
let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
|
||||
return ReducedTy::OrderedFields(ty);
|
||||
return ReducedTy::OrderedFields(ty, None);
|
||||
};
|
||||
if iter.all(|ty| is_zero_sized_ty(cx, ty)) {
|
||||
ty = sized_ty;
|
||||
@ -309,27 +277,25 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
|
||||
.iter()
|
||||
.map(|f| cx.tcx.bound_type_of(f.did).subst(cx.tcx, substs));
|
||||
let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
|
||||
return ReducedTy::TypeErasure;
|
||||
return ReducedTy::TypeErasure { raw_ptr_only: false };
|
||||
};
|
||||
if iter.all(|ty| is_zero_sized_ty(cx, ty)) {
|
||||
ty = sized_ty;
|
||||
continue;
|
||||
}
|
||||
if def.repr().inhibit_struct_field_reordering_opt() {
|
||||
ReducedTy::OrderedFields(ty)
|
||||
ReducedTy::OrderedFields(ty, Some(sized_ty))
|
||||
} else {
|
||||
ReducedTy::UnorderedFields(ty)
|
||||
}
|
||||
},
|
||||
ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => {
|
||||
ReducedTy::TypeErasure
|
||||
ReducedTy::TypeErasure { raw_ptr_only: false }
|
||||
},
|
||||
// TODO: Check if the conversion to or from at least one of a union's fields is valid.
|
||||
ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure,
|
||||
ty::Foreign(_) => ReducedTy::TypeErasure,
|
||||
ty::Ref(_, ty, _) => ReducedTy::Ref(ty),
|
||||
ty::RawPtr(ty) => ReducedTy::Ref(ty.ty),
|
||||
ty::Param(_) => ReducedTy::Param,
|
||||
ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false },
|
||||
ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false },
|
||||
ty::Int(_) | ty::Uint(_) => ReducedTy::TypeErasure { raw_ptr_only: true },
|
||||
_ => ReducedTy::Other(ty),
|
||||
};
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
use core::any::TypeId;
|
||||
use core::ffi::c_void;
|
||||
use core::mem::{size_of, transmute, MaybeUninit};
|
||||
use core::ptr::NonNull;
|
||||
|
||||
fn value<T>() -> T {
|
||||
unimplemented!()
|
||||
@ -109,6 +110,17 @@ fn main() {
|
||||
let _: Ty2<u32, u32> = transmute(value::<MaybeUninit<Ty2<u32, u32>>>()); // Ok
|
||||
|
||||
let _: Ty<&[u32]> = transmute::<&[u32], _>(value::<&Vec<u32>>()); // Ok
|
||||
|
||||
let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<Ty2<u32, u32>, u32>>()); // Ok
|
||||
let _: *const Ty2C<Ty2<u32, u32>, u32> = transmute(value::<*const Ty2<u32, u32>>()); // Ok
|
||||
let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<(), Ty2<u32, u32>>>()); // Ok
|
||||
let _: *const Ty2C<(), Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>()); // Ok
|
||||
|
||||
let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty2<u32, u32>>>()); // Err
|
||||
let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>()); // Err
|
||||
|
||||
let _: NonNull<u8> = transmute(value::<NonNull<(String, String)>>()); // Ok
|
||||
let _: NonNull<(String, String)> = transmute(value::<NonNull<u8>>()); // Ok
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: transmute from `Ty2<u32, i32>` which has an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:27:33
|
||||
--> $DIR/transmute_undefined_repr.rs:28:33
|
||||
|
|
||||
LL | let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,13 +7,13 @@ LL | let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lin
|
||||
= note: `-D clippy::transmute-undefined-repr` implied by `-D warnings`
|
||||
|
||||
error: transmute into `Ty2<u32, i32>` which has an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:28:32
|
||||
--> $DIR/transmute_undefined_repr.rs:29:32
|
||||
|
|
||||
LL | let _: Ty2<u32, i32> = transmute(value::<Ty2C<u32, i32>>()); // Lint, Ty2 is unordered
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: transmute from `Ty<Ty2<u32, i32>>` to `Ty2<u32, f32>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:33:32
|
||||
--> $DIR/transmute_undefined_repr.rs:34:32
|
||||
|
|
||||
LL | let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -21,7 +21,7 @@ LL | let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); //
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute from `Ty2<u32, f32>` to `Ty<Ty2<u32, i32>>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:34:36
|
||||
--> $DIR/transmute_undefined_repr.rs:35:36
|
||||
|
|
||||
LL | let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -29,7 +29,7 @@ LL | let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); //
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute from `Ty<&Ty2<u32, i32>>` to `&Ty2<u32, f32>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:39:33
|
||||
--> $DIR/transmute_undefined_repr.rs:40:33
|
||||
|
|
||||
LL | let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -37,7 +37,7 @@ LL | let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); /
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute from `&Ty2<u32, f32>` to `Ty<&Ty2<u32, i32>>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:40:37
|
||||
--> $DIR/transmute_undefined_repr.rs:41:37
|
||||
|
|
||||
LL | let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -45,7 +45,7 @@ LL | let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); /
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute from `std::boxed::Box<Ty2<u32, u32>>` to `&mut Ty2<u32, f32>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:57:45
|
||||
--> $DIR/transmute_undefined_repr.rs:58:45
|
||||
|
|
||||
LL | let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -53,15 +53,31 @@ LL | let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32,
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute from `&mut Ty2<u32, f32>` to `std::boxed::Box<Ty2<u32, u32>>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:58:37
|
||||
--> $DIR/transmute_undefined_repr.rs:59:37
|
||||
|
|
||||
LL | let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, f32>>()); // Lint, different Ty2 instances
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: two instances of the same generic type (`Ty2`) may have different layouts
|
||||
|
||||
error: transmute into `*const Ty2<u32, u32>` which has an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:119:39
|
||||
|
|
||||
LL | let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty2<u32, u32>>>()); // Err
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the contained type `Ty2<u32, u32>` has an undefined layout
|
||||
|
||||
error: transmute from `*const Ty2<u32, u32>` which has an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:120:50
|
||||
|
|
||||
LL | let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>()); // Err
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the contained type `Ty2<u32, u32>` has an undefined layout
|
||||
|
||||
error: transmute from `std::vec::Vec<Ty2<U, i32>>` to `std::vec::Vec<Ty2<T, u32>>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:138:35
|
||||
--> $DIR/transmute_undefined_repr.rs:150:35
|
||||
|
|
||||
LL | let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>()); // Err
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -69,12 +85,12 @@ LL | let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>()); /
|
||||
= note: two instances of the same generic type (`Vec`) may have different layouts
|
||||
|
||||
error: transmute from `std::vec::Vec<Ty2<T, u32>>` to `std::vec::Vec<Ty2<U, i32>>`, both of which have an undefined layout
|
||||
--> $DIR/transmute_undefined_repr.rs:139:35
|
||||
--> $DIR/transmute_undefined_repr.rs:151:35
|
||||
|
|
||||
LL | let _: Vec<Ty2<U, i32>> = transmute(value::<Vec<Ty2<T, u32>>>()); // Err
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: two instances of the same generic type (`Vec`) may have different layouts
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user