2022-02-10 17:40:06 +00:00
|
|
|
use super::TRANSMUTE_UNDEFINED_REPR;
|
|
|
|
use clippy_utils::diagnostics::span_lint_and_then;
|
|
|
|
use rustc_hir::Expr;
|
|
|
|
use rustc_lint::LateContext;
|
2022-02-07 15:06:55 +00:00
|
|
|
use rustc_middle::ty::subst::Subst;
|
2022-02-10 17:40:06 +00:00
|
|
|
use rustc_middle::ty::{self, Ty, TypeAndMut};
|
|
|
|
use rustc_span::Span;
|
|
|
|
|
|
|
|
#[allow(clippy::too_many_lines)]
|
|
|
|
pub(super) fn check<'tcx>(
|
|
|
|
cx: &LateContext<'tcx>,
|
|
|
|
e: &'tcx Expr<'_>,
|
|
|
|
from_ty_orig: Ty<'tcx>,
|
|
|
|
to_ty_orig: Ty<'tcx>,
|
|
|
|
) -> bool {
|
|
|
|
let mut from_ty = cx.tcx.erase_regions(from_ty_orig);
|
|
|
|
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, .. } => {
|
|
|
|
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;
|
|
|
|
},
|
|
|
|
ReducedTys::ToFatPtr { unsized_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() != unsized_ty {
|
|
|
|
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
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::IntArray, _) | (_, ReducedTy::IntArray) => return false,
|
|
|
|
(ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
|
|
|
|
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| {
|
2022-02-10 18:52:01 +00:00
|
|
|
if_chain! {
|
|
|
|
if let (Some(from_def), Some(to_def)) = (from_ty.ty_adt_def(), to_ty.ty_adt_def());
|
|
|
|
if from_def == to_def;
|
|
|
|
then {
|
|
|
|
diag.note(&format!(
|
|
|
|
"two instances of the same generic type (`{}`) may have different layouts",
|
|
|
|
cx.tcx.item_name(from_def.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));
|
|
|
|
}
|
2022-02-10 17:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
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| {
|
|
|
|
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::OrderedFields(_) | ReducedTy::Ref(_) | ReducedTy::Other(_),
|
|
|
|
)
|
|
|
|
| (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => break,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
enum ReducedTys<'tcx> {
|
|
|
|
FromFatPtr { unsized_ty: Ty<'tcx> },
|
|
|
|
ToFatPtr { unsized_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> },
|
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
|
|
|
(
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
&ty::Ref(_, from_sub_ty, _) | &ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. }),
|
|
|
|
&ty::Ref(_, to_sub_ty, _) | &ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. }),
|
2022-02-10 17:40:06 +00:00
|
|
|
) => {
|
|
|
|
from_ty = from_sub_ty;
|
|
|
|
to_ty = to_sub_ty;
|
|
|
|
continue;
|
|
|
|
},
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
(&ty::Ref(_, unsized_ty, _) | &ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }), _)
|
2022-02-10 17:40:06 +00:00
|
|
|
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
|
|
|
|
{
|
|
|
|
ReducedTys::FromFatPtr { unsized_ty }
|
|
|
|
},
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
(_, &ty::Ref(_, unsized_ty, _) | &ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))
|
2022-02-10 17:40:06 +00:00
|
|
|
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
|
|
|
|
{
|
|
|
|
ReducedTys::ToFatPtr { unsized_ty }
|
|
|
|
},
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
(&ty::Ref(_, from_ty, _) | &ty::RawPtr(TypeAndMut { ty: from_ty, .. }), _) => {
|
2022-02-10 17:40:06 +00:00
|
|
|
ReducedTys::FromPtr { from_ty, to_ty }
|
|
|
|
},
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
(_, &ty::Ref(_, to_ty, _) | &ty::RawPtr(TypeAndMut { ty: to_ty, .. })) => {
|
2022-02-10 17:40:06 +00:00
|
|
|
ReducedTys::ToPtr { from_ty, to_ty }
|
|
|
|
},
|
|
|
|
_ => ReducedTys::Other { from_ty, to_ty },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum ReducedTy<'tcx> {
|
|
|
|
OrderedFields(Ty<'tcx>),
|
|
|
|
UnorderedFields(Ty<'tcx>),
|
|
|
|
Ref(Ty<'tcx>),
|
|
|
|
Other(Ty<'tcx>),
|
|
|
|
IntArray,
|
|
|
|
}
|
|
|
|
|
|
|
|
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::IntArray,
|
|
|
|
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
|
|
|
|
ty = sub_ty;
|
|
|
|
continue;
|
|
|
|
},
|
|
|
|
ty::Tuple(args) => {
|
2022-02-07 15:06:55 +00:00
|
|
|
let Some(sized_ty) = args.iter().find(|&ty| !is_zero_sized_ty(cx, ty)) else {
|
2022-02-10 17:40:06 +00:00
|
|
|
return ReducedTy::OrderedFields(ty);
|
|
|
|
};
|
2022-02-07 15:06:55 +00:00
|
|
|
if args.iter().all(|ty| is_zero_sized_ty(cx, ty)) {
|
2022-02-10 17:40:06 +00:00
|
|
|
ty = sized_ty;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ReducedTy::UnorderedFields(ty)
|
|
|
|
},
|
|
|
|
ty::Adt(def, substs) if def.is_struct() => {
|
|
|
|
if def.repr.inhibit_struct_field_reordering_opt() {
|
|
|
|
return ReducedTy::OrderedFields(ty);
|
|
|
|
}
|
|
|
|
let mut iter = def
|
|
|
|
.non_enum_variant()
|
|
|
|
.fields
|
|
|
|
.iter()
|
|
|
|
.map(|f| cx.tcx.type_of(f.did).subst(cx.tcx, substs));
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
let Some(sized_ty) = iter.find(|ty| !is_zero_sized_ty(cx, *ty)) else {
|
2022-02-10 17:40:06 +00:00
|
|
|
return ReducedTy::OrderedFields(ty);
|
|
|
|
};
|
|
|
|
if iter.all(|ty| is_zero_sized_ty(cx, ty)) {
|
|
|
|
ty = sized_ty;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ReducedTy::UnorderedFields(ty)
|
|
|
|
},
|
|
|
|
ty::Ref(..) | ty::RawPtr(_) => ReducedTy::Ref(ty),
|
|
|
|
_ => ReducedTy::Other(ty),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
2022-02-10 18:52:01 +00:00
|
|
|
if_chain! {
|
|
|
|
if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty);
|
|
|
|
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
|
|
|
|
then {
|
|
|
|
layout.layout.size.bytes() == 0
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
2022-02-10 17:40:06 +00:00
|
|
|
}
|
|
|
|
}
|