Sorting arbitrary constants should not be done, as it relies on DefId
ordering, which breaks incremental compilation.
This commit is contained in:
parent
cda209bf43
commit
d8470bb00b
@ -2,7 +2,7 @@
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::query::TyCtxtAt;
|
||||
use crate::ty::normalize_erasing_regions::NormalizationError;
|
||||
use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_error_messages::DiagMessage;
|
||||
use rustc_errors::{
|
||||
Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
|
||||
@ -356,21 +356,10 @@ pub fn compute(
|
||||
.ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
|
||||
}
|
||||
let len = tcx.expand_abstract_consts(len);
|
||||
let prev = ty::Const::from_target_usize(tcx, s.bytes());
|
||||
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
|
||||
return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
|
||||
};
|
||||
Ok(SizeSkeleton::Generic(gen_size))
|
||||
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
|
||||
}
|
||||
SizeSkeleton::Pointer { .. } => Err(err),
|
||||
SizeSkeleton::Generic(g) => {
|
||||
let len = tcx.expand_abstract_consts(len);
|
||||
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
|
||||
return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
|
||||
};
|
||||
Ok(SizeSkeleton::Generic(gen_size))
|
||||
}
|
||||
SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,56 +457,6 @@ pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
|
||||
/// to ensure that they have a canonical order and can be compared directly we combine all
|
||||
/// constants, and sort the other terms. This allows comparison of expressions of sizes,
|
||||
/// allowing for things like transmuting between types that depend on generic consts.
|
||||
/// This returns `None` if multiplication of constants overflows.
|
||||
fn mul_sorted_consts<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
a: ty::Const<'tcx>,
|
||||
b: ty::Const<'tcx>,
|
||||
) -> Option<ty::Const<'tcx>> {
|
||||
use crate::mir::BinOp::Mul;
|
||||
|
||||
let mut work = vec![a, b];
|
||||
let mut done = vec![];
|
||||
while let Some(n) = work.pop() {
|
||||
if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() {
|
||||
work.push(l);
|
||||
work.push(r)
|
||||
} else {
|
||||
done.push(n);
|
||||
}
|
||||
}
|
||||
let mut k = 1;
|
||||
let mut overflow = false;
|
||||
done.retain(|c| {
|
||||
let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
|
||||
return true;
|
||||
};
|
||||
let Some(next) = c.checked_mul(k) else {
|
||||
overflow = true;
|
||||
return false;
|
||||
};
|
||||
k = next;
|
||||
false
|
||||
});
|
||||
if overflow {
|
||||
return None;
|
||||
}
|
||||
if k != 1 {
|
||||
done.push(ty::Const::from_target_usize(tcx, k));
|
||||
} else if k == 0 {
|
||||
return Some(ty::Const::from_target_usize(tcx, 0));
|
||||
}
|
||||
done.sort_unstable();
|
||||
|
||||
// create a single tree from the buffer
|
||||
done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty()))
|
||||
}
|
||||
|
||||
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
}
|
||||
|
@ -32,4 +32,79 @@
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_3d<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [u32; D * W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [[u32; D * W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose_with_const<const W: usize, const H: usize>(
|
||||
v: [[u32; 2 * H]; W + W]
|
||||
) -> [[u32; W + W]; 2 * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W)
|
||||
= note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H)
|
||||
= note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
|
||||
= note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:16:5
|
||||
@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (generic size 4 * H * W)
|
||||
= note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W)
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:30:5
|
||||
@ -34,6 +34,87 @@ LL | std::mem::transmute(v)
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:37:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:50:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[u32; W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:57:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u32; H*W]` (this type does not have a fixed size)
|
||||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:66:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
|
||||
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:75:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
|
||||
= note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:82:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u16; L]` (this type does not have a fixed size)
|
||||
= note: target type: `[u8; L * 2]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:89:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u8; L * 2]` (this type does not have a fixed size)
|
||||
= note: target type: `[u16; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:96:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u8; L]` (this type does not have a fixed size)
|
||||
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:105:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
|
||||
= note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transmute-fail.rs:12:53
|
||||
|
|
||||
@ -46,7 +127,7 @@ error[E0308]: mismatched types
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^ expected `usize`, found `bool`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0512.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -3,81 +3,12 @@
|
||||
#![feature(transmute_generic_consts)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_3d<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [u32; D * W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [[u32; D * W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose_with_const<const W: usize, const H: usize>(
|
||||
v: [[u32; 2 * H]; W + W]
|
||||
) -> [[u32; W + W]; 2 * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = transpose([[0; 8]; 16]);
|
||||
let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
|
||||
let _ = ident([[0; 8]; 16]);
|
||||
let _ = flatten([[0; 13]; 5]);
|
||||
let _: [[_; 5]; 13] = coagulate([0; 65]);
|
||||
let _ = flatten_3d([[[0; 3]; 13]; 5]);
|
||||
let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
|
||||
let _ = known_size([16; 13]);
|
||||
let _: [u16; 5] = condense_bytes([16u8; 10]);
|
||||
let _ = singleton_each([16; 10]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user