1
Fork 0

Auto merge of #130950 - compiler-errors:yeet-eval, r=BoxyUwU

Continue to get rid of `ty::Const::{try_}eval*`

This PR mostly does:

* Removes all of the `try_eval_*` and `eval_*` helpers from `ty::Const`, and replace their usages with `try_to_*`.
* Remove `ty::Const::eval`.
* Rename `ty::Const::normalize` to `ty::Const::normalize_internal`. This function is still used in the normalization code itself.
* Fix some weirdness around the `TransmuteFrom` goal.

I'm happy to split it out further; for example, I could probably land the first part which removes the helpers, or the changes to codegen which are more obvious than the changes to tools.

r? BoxyUwU

Part of https://github.com/rust-lang/rust/issues/130704
This commit is contained in:
bors 2024-10-21 03:46:28 +00:00
commit f2ba41113d
58 changed files with 407 additions and 338 deletions

View file

@ -2230,124 +2230,143 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
span: Span,
) -> GetSafeTransmuteErrorAndReason {
use rustc_transmute::Answer;
self.probe(|_| {
// We don't assemble a transmutability candidate for types that are generic
// and we should have ambiguity for types that still have non-region infer.
if obligation.predicate.has_non_region_param() || obligation.has_non_region_infer() {
return GetSafeTransmuteErrorAndReason::Default;
}
// We don't assemble a transmutability candidate for types that are generic
// and we should have ambiguity for types that still have non-region infer.
if obligation.predicate.has_non_region_param() || obligation.has_non_region_infer() {
return GetSafeTransmuteErrorAndReason::Default;
}
// Erase regions because layout code doesn't particularly care about regions.
let trait_ref =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
// Erase regions because layout code doesn't particularly care about regions.
let trait_ref =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
let src_and_dst = rustc_transmute::Types {
dst: trait_ref.args.type_at(0),
src: trait_ref.args.type_at(1),
};
let src_and_dst = rustc_transmute::Types {
dst: trait_ref.args.type_at(0),
src: trait_ref.args.type_at(1),
};
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
obligation.param_env,
trait_ref.args.const_at(2),
) else {
self.dcx().span_delayed_bug(
span,
"Unable to construct rustc_transmute::Assume where it was previously possible",
);
return GetSafeTransmuteErrorAndReason::Silent;
};
let ocx = ObligationCtxt::new(self);
let Ok(assume) = ocx.structurally_normalize_const(
&obligation.cause,
obligation.param_env,
trait_ref.args.const_at(2),
) else {
self.dcx().span_delayed_bug(
span,
"Unable to construct rustc_transmute::Assume where it was previously possible",
);
return GetSafeTransmuteErrorAndReason::Silent;
};
let dst = trait_ref.args.type_at(0);
let src = trait_ref.args.type_at(1);
let Some(assume) =
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, assume)
else {
self.dcx().span_delayed_bug(
span,
"Unable to construct rustc_transmute::Assume where it was previously possible",
);
return GetSafeTransmuteErrorAndReason::Silent;
};
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
let dst = trait_ref.args.type_at(0);
let src = trait_ref.args.type_at(1);
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
assume,
) {
Answer::No(reason) => {
let safe_transmute_explanation = match reason {
rustc_transmute::Reason::SrcIsNotYetSupported => {
format!("analyzing the transmutability of `{src}` is not yet supported")
}
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
assume,
) {
Answer::No(reason) => {
let safe_transmute_explanation = match reason {
rustc_transmute::Reason::SrcIsNotYetSupported => {
format!("analyzing the transmutability of `{src}` is not yet supported")
}
rustc_transmute::Reason::DstIsNotYetSupported => {
format!("analyzing the transmutability of `{dst}` is not yet supported")
}
rustc_transmute::Reason::DstIsNotYetSupported => {
format!("analyzing the transmutability of `{dst}` is not yet supported")
}
rustc_transmute::Reason::DstIsBitIncompatible => {
format!("at least one value of `{src}` isn't a bit-valid value of `{dst}`")
}
rustc_transmute::Reason::DstIsBitIncompatible => {
format!(
"at least one value of `{src}` isn't a bit-valid value of `{dst}`"
)
}
rustc_transmute::Reason::DstUninhabited => {
format!("`{dst}` is uninhabited")
}
rustc_transmute::Reason::DstUninhabited => {
format!("`{dst}` is uninhabited")
}
rustc_transmute::Reason::DstMayHaveSafetyInvariants => {
format!("`{dst}` may carry safety invariants")
rustc_transmute::Reason::DstMayHaveSafetyInvariants => {
format!("`{dst}` may carry safety invariants")
}
rustc_transmute::Reason::DstIsTooBig => {
format!("the size of `{src}` is smaller than the size of `{dst}`")
}
rustc_transmute::Reason::DstRefIsTooBig { src, dst } => {
let src_size = src.size;
let dst_size = dst.size;
format!(
"the referent size of `{src}` ({src_size} bytes) \
is smaller than that of `{dst}` ({dst_size} bytes)"
)
}
rustc_transmute::Reason::SrcSizeOverflow => {
format!(
"values of the type `{src}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstSizeOverflow => {
format!(
"values of the type `{dst}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstHasStricterAlignment {
src_min_align,
dst_min_align,
} => {
format!(
"the minimum alignment of `{src}` ({src_min_align}) should \
be greater than that of `{dst}` ({dst_min_align})"
)
}
rustc_transmute::Reason::DstIsMoreUnique => {
format!(
"`{src}` is a shared reference, but `{dst}` is a unique reference"
)
}
// Already reported by rustc
rustc_transmute::Reason::TypeError => {
return GetSafeTransmuteErrorAndReason::Silent;
}
rustc_transmute::Reason::SrcLayoutUnknown => {
format!("`{src}` has an unknown layout")
}
rustc_transmute::Reason::DstLayoutUnknown => {
format!("`{dst}` has an unknown layout")
}
};
GetSafeTransmuteErrorAndReason::Error {
err_msg,
safe_transmute_explanation: Some(safe_transmute_explanation),
}
rustc_transmute::Reason::DstIsTooBig => {
format!("the size of `{src}` is smaller than the size of `{dst}`")
}
rustc_transmute::Reason::DstRefIsTooBig { src, dst } => {
let src_size = src.size;
let dst_size = dst.size;
format!(
"the referent size of `{src}` ({src_size} bytes) is smaller than that of `{dst}` ({dst_size} bytes)"
)
}
rustc_transmute::Reason::SrcSizeOverflow => {
format!(
"values of the type `{src}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstSizeOverflow => {
format!(
"values of the type `{dst}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstHasStricterAlignment {
src_min_align,
dst_min_align,
} => {
format!(
"the minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})"
)
}
rustc_transmute::Reason::DstIsMoreUnique => {
format!("`{src}` is a shared reference, but `{dst}` is a unique reference")
}
// Already reported by rustc
rustc_transmute::Reason::TypeError => {
return GetSafeTransmuteErrorAndReason::Silent;
}
rustc_transmute::Reason::SrcLayoutUnknown => {
format!("`{src}` has an unknown layout")
}
rustc_transmute::Reason::DstLayoutUnknown => {
format!("`{dst}` has an unknown layout")
}
};
GetSafeTransmuteErrorAndReason::Error {
err_msg,
safe_transmute_explanation: Some(safe_transmute_explanation),
}
// Should never get a Yes at this point! We already ran it before, and did not get a Yes.
Answer::Yes => span_bug!(
span,
"Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
),
// Reached when a different obligation (namely `Freeze`) causes the
// transmutability analysis to fail. In this case, silence the
// transmutability error message in favor of that more specific
// error.
Answer::If(_) => GetSafeTransmuteErrorAndReason::Error {
err_msg,
safe_transmute_explanation: None,
},
}
// Should never get a Yes at this point! We already ran it before, and did not get a Yes.
Answer::Yes => span_bug!(
span,
"Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
),
// Reached when a different obligation (namely `Freeze`) causes the
// transmutability analysis to fail. In this case, silence the
// transmutability error message in favor of that more specific
// error.
Answer::If(_) => {
GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation: None }
}
}
})
}
/// For effects predicates such as `<u32 as Add>::Effects: Compat<host>`, pretend that the

View file

@ -231,7 +231,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string())));
let len = len.try_to_valtree().and_then(|v| v.try_to_target_usize(self.tcx));
let len = len.try_to_target_usize(self.tcx);
flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));

View file

@ -329,4 +329,15 @@ where
.at(cause, param_env)
.structurally_normalize(value, &mut **self.engine.borrow_mut())
}
pub fn structurally_normalize_const(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: ty::Const<'tcx>,
) -> Result<ty::Const<'tcx>, Vec<E>> {
self.infcx
.at(cause, param_env)
.structurally_normalize_const(value, &mut **self.engine.borrow_mut())
}
}

View file

@ -368,7 +368,7 @@ pub fn normalize_param_env_or_error<'tcx>(
// should actually be okay since without `feature(generic_const_exprs)` the only
// const arguments that have a non-empty param env are array repeat counts. These
// do not appear in the type system though.
c.normalize(self.0, ty::ParamEnv::empty())
c.normalize_internal(self.0, ty::ParamEnv::empty())
}
}

View file

@ -413,7 +413,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
self.selcx.infcx,
&mut self.universes,
constant,
|constant| constant.normalize(tcx, self.param_env),
|constant| constant.normalize_internal(tcx, self.param_env),
)
}
}

View file

@ -340,7 +340,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
self.infcx,
&mut self.universes,
constant,
|constant| constant.normalize(self.infcx.tcx, self.param_env),
|constant| constant.normalize_internal(self.infcx.tcx, self.param_env),
);
debug!(?constant, ?self.param_env);
constant.try_super_fold_with(self)

View file

@ -405,11 +405,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let predicate = obligation.predicate.skip_binder();
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
obligation.param_env,
predicate.trait_ref.args.const_at(2),
) else {
let mut assume = predicate.trait_ref.args.const_at(2);
// FIXME(min_generic_const_exprs): We should shallowly normalize this.
if self.tcx().features().generic_const_exprs {
assume = assume.normalize_internal(self.tcx(), obligation.param_env);
}
let Some(assume) =
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, assume)
else {
return Err(Unimplemented);
};

View file

@ -82,6 +82,8 @@ impl<'tcx> At<'_, 'tcx> {
}
Ok(self.infcx.resolve_vars_if_possible(new_infer_ct))
} else if self.infcx.tcx.features().generic_const_exprs {
Ok(ct.normalize_internal(self.infcx.tcx, self.param_env))
} else {
Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx))
}