Rollup merge of #122820 - oli-obk:no_ord_def_id, r=estebank
Stop using `<DefId as Ord>` in various diagnostic situations work towards https://github.com/rust-lang/rust/issues/90317 Reverts part of https://github.com/rust-lang/rust/pull/106281, as it sorts constants and that's problematic since it can contain `ParamConst`, which contains `DefId`s
This commit is contained in:
commit
7481c0eab5
10 changed files with 197 additions and 161 deletions
|
@ -456,7 +456,7 @@ impl<'tcx> Const<'tcx> {
|
|||
}
|
||||
|
||||
/// An unevaluated (potentially generic) constant used in MIR.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct UnevaluatedConst<'tcx> {
|
||||
pub def: DefId,
|
||||
|
|
|
@ -284,8 +284,15 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
|
|||
/// order of the category, thereby influencing diagnostic output.
|
||||
///
|
||||
/// See also `rustc_const_eval::borrow_check::constraints`.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
PartialOrd,
|
||||
Ord,
|
||||
PartialOrd = "feature_allow_slow_enum",
|
||||
Ord = "feature_allow_slow_enum"
|
||||
)]
|
||||
pub enum ConstraintCategory<'tcx> {
|
||||
Return(ReturnConstraint),
|
||||
Yield,
|
||||
|
@ -295,6 +302,7 @@ pub enum ConstraintCategory<'tcx> {
|
|||
Cast {
|
||||
/// Whether this is an unsizing cast and if yes, this contains the target type.
|
||||
/// Region variables are erased to ReErased.
|
||||
#[derivative(PartialOrd = "ignore", Ord = "ignore")]
|
||||
unsize_to: Option<Ty<'tcx>>,
|
||||
},
|
||||
|
||||
|
@ -304,7 +312,7 @@ pub enum ConstraintCategory<'tcx> {
|
|||
ClosureBounds,
|
||||
|
||||
/// Contains the function type if available.
|
||||
CallArgument(Option<Ty<'tcx>>),
|
||||
CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option<Ty<'tcx>>),
|
||||
CopyBound,
|
||||
SizedBound,
|
||||
Assignment,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi;
|
|||
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 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
.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 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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>;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue