Use `tidy` to sort crate attributes for all compiler crates.
We already do this for a number of crates, e.g. `rustc_middle`,
`rustc_span`, `rustc_metadata`, `rustc_span`, `rustc_errors`.
For the ones we don't, in many cases the attributes are a mess.
- There is no consistency about order of attribute kinds (e.g.
`allow`/`deny`/`feature`).
- Within attribute kind groups (e.g. the `feature` attributes),
sometimes the order is alphabetical, and sometimes there is no
particular order.
- Sometimes the attributes of a particular kind aren't even grouped
all together, e.g. there might be a `feature`, then an `allow`, then
another `feature`.
This commit extends the existing sorting to all compiler crates,
increasing consistency. If any new attribute line is added there is now
only one place it can go -- no need for arbitrary decisions.
Exceptions:
- `rustc_log`, `rustc_next_trait_solver` and `rustc_type_ir_macros`,
because they have no crate attributes.
- `rustc_codegen_gcc`, because it's quasi-external to rustc (e.g. it's
ignored in `rustfmt.toml`).
2024-06-12 03:49:36 +00:00
|
|
|
// tidy-alphabetical-start
|
|
|
|
#![allow(unused_variables)]
|
2024-01-14 20:08:47 +00:00
|
|
|
#![feature(alloc_layout_extra)]
|
|
|
|
#![feature(never_type)]
|
2024-08-30 06:15:56 +00:00
|
|
|
#![warn(unreachable_pub)]
|
Use `tidy` to sort crate attributes for all compiler crates.
We already do this for a number of crates, e.g. `rustc_middle`,
`rustc_span`, `rustc_metadata`, `rustc_span`, `rustc_errors`.
For the ones we don't, in many cases the attributes are a mess.
- There is no consistency about order of attribute kinds (e.g.
`allow`/`deny`/`feature`).
- Within attribute kind groups (e.g. the `feature` attributes),
sometimes the order is alphabetical, and sometimes there is no
particular order.
- Sometimes the attributes of a particular kind aren't even grouped
all together, e.g. there might be a `feature`, then an `allow`, then
another `feature`.
This commit extends the existing sorting to all compiler crates,
increasing consistency. If any new attribute line is added there is now
only one place it can go -- no need for arbitrary decisions.
Exceptions:
- `rustc_log`, `rustc_next_trait_solver` and `rustc_type_ir_macros`,
because they have no crate attributes.
- `rustc_codegen_gcc`, because it's quasi-external to rustc (e.g. it's
ignored in `rustfmt.toml`).
2024-06-12 03:49:36 +00:00
|
|
|
// tidy-alphabetical-end
|
2021-07-03 16:18:13 +00:00
|
|
|
|
2022-08-23 15:52:49 +00:00
|
|
|
pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
|
2021-07-03 16:18:13 +00:00
|
|
|
|
2023-04-21 23:49:36 +00:00
|
|
|
pub mod layout;
|
2023-10-05 23:16:54 +00:00
|
|
|
mod maybe_transmutable;
|
2021-07-03 16:18:13 +00:00
|
|
|
|
2024-08-14 20:10:28 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Default)]
|
2021-07-03 16:18:13 +00:00
|
|
|
pub struct Assume {
|
|
|
|
pub alignment: bool,
|
|
|
|
pub lifetimes: bool,
|
2022-08-18 19:39:14 +00:00
|
|
|
pub safety: bool,
|
2021-07-03 16:18:13 +00:00
|
|
|
pub validity: bool,
|
|
|
|
}
|
|
|
|
|
2023-10-05 23:17:29 +00:00
|
|
|
/// Either transmutation is allowed, we have an error, or we have an optional
|
2023-06-12 23:35:23 +00:00
|
|
|
/// Condition that must hold.
|
|
|
|
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
|
|
|
|
pub enum Answer<R> {
|
|
|
|
Yes,
|
2024-03-13 00:11:36 +00:00
|
|
|
No(Reason<R>),
|
2023-06-12 23:35:23 +00:00
|
|
|
If(Condition<R>),
|
|
|
|
}
|
2021-07-03 16:18:13 +00:00
|
|
|
|
2023-06-12 23:35:23 +00:00
|
|
|
/// A condition which must hold for safe transmutation to be possible.
|
2023-04-27 21:38:32 +00:00
|
|
|
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
|
|
|
|
pub enum Condition<R> {
|
2021-07-03 16:18:13 +00:00
|
|
|
/// `Src` is transmutable into `Dst`, if `src` is transmutable into `dst`.
|
|
|
|
IfTransmutable { src: R, dst: R },
|
|
|
|
|
|
|
|
/// `Src` is transmutable into `Dst`, if all of the enclosed requirements are met.
|
2023-05-25 00:47:13 +00:00
|
|
|
IfAll(Vec<Condition<R>>),
|
2021-07-03 16:18:13 +00:00
|
|
|
|
|
|
|
/// `Src` is transmutable into `Dst` if any of the enclosed requirements are met.
|
2023-05-25 00:47:13 +00:00
|
|
|
IfAny(Vec<Condition<R>>),
|
2021-07-03 16:18:13 +00:00
|
|
|
}
|
|
|
|
|
2023-06-12 23:35:23 +00:00
|
|
|
/// Answers "why wasn't the source type transmutable into the destination type?"
|
2021-07-03 16:18:13 +00:00
|
|
|
#[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
|
2024-03-13 00:11:36 +00:00
|
|
|
pub enum Reason<T> {
|
2024-03-15 17:11:11 +00:00
|
|
|
/// The layout of the source type is not yet supported.
|
|
|
|
SrcIsNotYetSupported,
|
|
|
|
/// The layout of the destination type is not yet supported.
|
|
|
|
DstIsNotYetSupported,
|
2021-07-03 16:18:13 +00:00
|
|
|
/// The layout of the destination type is bit-incompatible with the source type.
|
|
|
|
DstIsBitIncompatible,
|
Compute transmutability from `rustc_target::abi::Layout`
In its first step of computing transmutability, `rustc_transmutability`
constructs a byte-level representation of type layout (`Tree`). Previously, this
representation was computed for ADTs by inspecting the ADT definition and
performing our own layout computations. This process was error-prone, verbose,
and limited our ability to analyze many types (particularly default-repr types).
In this PR, we instead construct `Tree`s from `rustc_target::abi::Layout`s. This
helps ensure that layout optimizations are reflected our analyses, and increases
the kinds of types we can now analyze, including:
- default repr ADTs
- transparent unions
- `UnsafeCell`-containing types
Overall, this PR expands the expressvity of `rustc_transmutability` to be much
closer to the transmutability analysis performed by miri. Future PRs will work
to close the remaining gaps (e.g., support for `Box`, raw pointers, `NonZero*`,
coroutines, etc.).
2024-03-19 14:49:13 +00:00
|
|
|
/// The destination type is uninhabited.
|
|
|
|
DstUninhabited,
|
2024-02-26 16:49:25 +00:00
|
|
|
/// The destination type may carry safety invariants.
|
|
|
|
DstMayHaveSafetyInvariants,
|
2021-07-03 16:18:13 +00:00
|
|
|
/// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized.
|
|
|
|
DstIsTooBig,
|
2024-03-13 00:11:36 +00:00
|
|
|
/// A referent of `Dst` is larger than a referent in `Src`.
|
|
|
|
DstRefIsTooBig {
|
|
|
|
/// The referent of the source type.
|
|
|
|
src: T,
|
|
|
|
/// The too-large referent of the destination type.
|
|
|
|
dst: T,
|
|
|
|
},
|
2023-04-21 23:49:36 +00:00
|
|
|
/// Src should have a stricter alignment than Dst, but it does not.
|
2023-05-25 00:47:13 +00:00
|
|
|
DstHasStricterAlignment { src_min_align: usize, dst_min_align: usize },
|
2023-04-21 23:49:36 +00:00
|
|
|
/// Can't go from shared pointer to unique pointer
|
|
|
|
DstIsMoreUnique,
|
2023-06-12 23:35:23 +00:00
|
|
|
/// Encountered a type error
|
|
|
|
TypeError,
|
|
|
|
/// The layout of src is unknown
|
|
|
|
SrcLayoutUnknown,
|
|
|
|
/// The layout of dst is unknown
|
|
|
|
DstLayoutUnknown,
|
2023-09-03 02:58:13 +00:00
|
|
|
/// The size of src is overflow
|
|
|
|
SrcSizeOverflow,
|
|
|
|
/// The size of dst is overflow
|
|
|
|
DstSizeOverflow,
|
2021-07-03 16:18:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "rustc")]
|
|
|
|
mod rustc {
|
2022-08-18 19:39:14 +00:00
|
|
|
use rustc_hir::lang_items::LangItem;
|
2021-07-03 16:18:13 +00:00
|
|
|
use rustc_infer::infer::InferCtxt;
|
2023-04-16 21:16:25 +00:00
|
|
|
use rustc_macros::TypeVisitable;
|
2021-07-03 16:18:13 +00:00
|
|
|
use rustc_middle::traits::ObligationCause;
|
2025-02-08 04:13:28 +00:00
|
|
|
use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt};
|
2021-07-03 16:18:13 +00:00
|
|
|
|
2022-08-18 19:39:14 +00:00
|
|
|
use super::*;
|
2024-07-28 22:13:50 +00:00
|
|
|
|
2021-07-03 16:18:13 +00:00
|
|
|
/// The source and destination types of a transmutation.
|
2023-04-16 21:16:25 +00:00
|
|
|
#[derive(TypeVisitable, Debug, Clone, Copy)]
|
2021-07-03 16:18:13 +00:00
|
|
|
pub struct Types<'tcx> {
|
|
|
|
/// The source type.
|
|
|
|
pub src: Ty<'tcx>,
|
|
|
|
/// The destination type.
|
|
|
|
pub dst: Ty<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TransmuteTypeEnv<'cx, 'tcx> {
|
2022-09-09 18:01:06 +00:00
|
|
|
infcx: &'cx InferCtxt<'tcx>,
|
2021-07-03 16:18:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'cx, 'tcx> TransmuteTypeEnv<'cx, 'tcx> {
|
2022-09-09 18:01:06 +00:00
|
|
|
pub fn new(infcx: &'cx InferCtxt<'tcx>) -> Self {
|
2021-07-03 16:18:13 +00:00
|
|
|
Self { infcx }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(unused)]
|
|
|
|
pub fn is_transmutable(
|
|
|
|
&mut self,
|
|
|
|
cause: ObligationCause<'tcx>,
|
2023-04-07 05:25:56 +00:00
|
|
|
types: Types<'tcx>,
|
2021-07-03 16:18:13 +00:00
|
|
|
assume: crate::Assume,
|
|
|
|
) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
|
|
|
|
crate::maybe_transmutable::MaybeTransmutableQuery::new(
|
2023-04-07 05:25:56 +00:00
|
|
|
types.src,
|
|
|
|
types.dst,
|
2021-07-03 16:18:13 +00:00
|
|
|
assume,
|
|
|
|
self.infcx.tcx,
|
|
|
|
)
|
|
|
|
.answer()
|
|
|
|
}
|
|
|
|
}
|
2022-08-18 19:39:14 +00:00
|
|
|
|
|
|
|
impl Assume {
|
|
|
|
/// Constructs an `Assume` from a given const-`Assume`.
|
|
|
|
pub fn from_const<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
param_env: ParamEnv<'tcx>,
|
2025-01-27 03:30:00 +00:00
|
|
|
ct: Const<'tcx>,
|
2022-10-03 08:51:18 +00:00
|
|
|
) -> Option<Self> {
|
2022-08-31 18:17:32 +00:00
|
|
|
use rustc_middle::ty::ScalarInt;
|
2024-12-12 23:29:23 +00:00
|
|
|
use rustc_span::sym;
|
2022-08-18 19:39:14 +00:00
|
|
|
|
2025-01-27 03:30:00 +00:00
|
|
|
let Some(cv) = ct.try_to_value() else {
|
2024-09-27 18:24:31 +00:00
|
|
|
return None;
|
2023-09-12 21:28:25 +00:00
|
|
|
};
|
2022-08-18 19:39:14 +00:00
|
|
|
|
2025-01-27 03:30:00 +00:00
|
|
|
let adt_def = cv.ty.ty_adt_def()?;
|
2022-08-18 19:39:14 +00:00
|
|
|
|
2025-02-08 04:13:28 +00:00
|
|
|
if !tcx.is_lang_item(adt_def.did(), LangItem::TransmuteOpts) {
|
|
|
|
tcx.dcx().delayed_bug(format!(
|
|
|
|
"The given `const` was not marked with the `{}` lang item.",
|
|
|
|
LangItem::TransmuteOpts.name()
|
|
|
|
));
|
|
|
|
return Some(Self {
|
|
|
|
alignment: true,
|
|
|
|
lifetimes: true,
|
|
|
|
safety: true,
|
|
|
|
validity: true,
|
|
|
|
});
|
|
|
|
}
|
2022-08-18 19:39:14 +00:00
|
|
|
|
2022-08-31 18:17:32 +00:00
|
|
|
let variant = adt_def.non_enum_variant();
|
2025-02-08 04:13:28 +00:00
|
|
|
let fields = cv.valtree.unwrap_branch();
|
2022-08-18 19:39:14 +00:00
|
|
|
|
|
|
|
let get_field = |name| {
|
|
|
|
let (field_idx, _) = variant
|
|
|
|
.fields
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find(|(_, field_def)| name == field_def.name)
|
2023-04-09 19:52:46 +00:00
|
|
|
.unwrap_or_else(|| panic!("There were no fields named `{name}`."));
|
2022-08-31 18:17:32 +00:00
|
|
|
fields[field_idx].unwrap_leaf() == ScalarInt::TRUE
|
2022-08-18 19:39:14 +00:00
|
|
|
};
|
|
|
|
|
2022-10-03 08:51:18 +00:00
|
|
|
Some(Self {
|
2022-08-18 19:39:14 +00:00
|
|
|
alignment: get_field(sym::alignment),
|
|
|
|
lifetimes: get_field(sym::lifetimes),
|
|
|
|
safety: get_field(sym::safety),
|
|
|
|
validity: get_field(sym::validity),
|
2022-10-03 08:51:18 +00:00
|
|
|
})
|
2022-08-18 19:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-03 16:18:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "rustc")]
|
|
|
|
pub use rustc::*;
|