Rollup merge of #151703 - zedddie:fix-151462-ice, r=jdonszelmann
Fix ICE in transmutability error reporting when type aliases are normalized Fixes rust-lang/rust#151462 Transmutability error reporting hit an ICE when type aliases were normalized for diagnostics. For example, when type `JustUnit = ()` normalizes to `()`, the check passes unexpectedly even though the original check with `JustUnit` failed. Fixed by adding a retry in the `Answer::Yes` arm that checks with the root obligation's types before panicking. The retry only occurs when the root obligation differs and is a Transmute trait predicate. Also added a test that reproduces the original ICE.
This commit is contained in:
commit
29ecd0fff5
3 changed files with 114 additions and 2 deletions
|
|
@ -254,9 +254,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
LangItem::TransmuteTrait,
|
||||
) {
|
||||
// Recompute the safe transmute reason and use that for the error reporting
|
||||
let (report_obligation, report_pred) =
|
||||
self.select_transmute_obligation_for_reporting(
|
||||
&obligation,
|
||||
main_trait_predicate,
|
||||
root_obligation,
|
||||
);
|
||||
|
||||
match self.get_safe_transmute_error_and_reason(
|
||||
obligation.clone(),
|
||||
main_trait_predicate,
|
||||
report_obligation,
|
||||
report_pred,
|
||||
span,
|
||||
) {
|
||||
GetSafeTransmuteErrorAndReason::Silent => {
|
||||
|
|
@ -2825,6 +2832,51 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn select_transmute_obligation_for_reporting(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_predicate: ty::PolyTraitPredicate<'tcx>,
|
||||
root_obligation: &PredicateObligation<'tcx>,
|
||||
) -> (PredicateObligation<'tcx>, ty::PolyTraitPredicate<'tcx>) {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let normalized_predicate = self.tcx.erase_and_anonymize_regions(
|
||||
self.tcx.instantiate_bound_regions_with_erased(trait_predicate),
|
||||
);
|
||||
let trait_ref = normalized_predicate.trait_ref;
|
||||
|
||||
let Ok(assume) = ocx.structurally_normalize_const(
|
||||
&obligation.cause,
|
||||
obligation.param_env,
|
||||
trait_ref.args.const_at(2),
|
||||
) else {
|
||||
return (obligation.clone(), trait_predicate);
|
||||
};
|
||||
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else {
|
||||
return (obligation.clone(), trait_predicate);
|
||||
};
|
||||
|
||||
let is_normalized_yes = matches!(
|
||||
rustc_transmute::TransmuteTypeEnv::new(self.tcx).is_transmutable(
|
||||
trait_ref.args.type_at(1),
|
||||
trait_ref.args.type_at(0),
|
||||
assume,
|
||||
),
|
||||
rustc_transmute::Answer::Yes,
|
||||
);
|
||||
|
||||
// If the normalized check unexpectedly passes, fall back to root obligation for reporting.
|
||||
if is_normalized_yes
|
||||
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(root_pred)) =
|
||||
root_obligation.predicate.kind().skip_binder()
|
||||
&& root_pred.def_id() == trait_predicate.def_id()
|
||||
{
|
||||
return (root_obligation.clone(), root_obligation.predicate.kind().rebind(root_pred));
|
||||
}
|
||||
|
||||
(obligation.clone(), trait_predicate)
|
||||
}
|
||||
|
||||
fn get_safe_transmute_error_and_reason(
|
||||
&self,
|
||||
obligation: PredicateObligation<'tcx>,
|
||||
|
|
|
|||
31
tests/ui/transmutability/type-alias-normalization.rs
Normal file
31
tests/ui/transmutability/type-alias-normalization.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//! regression test for https://github.com/rust-lang/rust/issues/151462
|
||||
//@compile-flags: -Znext-solver=globally
|
||||
#![feature(lazy_type_alias, transmutability)]
|
||||
#![allow(incomplete_features)]
|
||||
mod assert {
|
||||
use std::mem::{Assume, TransmuteFrom};
|
||||
|
||||
pub fn is_maybe_transmutable<Src, Dst>()
|
||||
where
|
||||
Src: TransmuteFrom<
|
||||
Src,
|
||||
{
|
||||
Assume {
|
||||
alignment: true,
|
||||
lifetimes: true,
|
||||
safety: true,
|
||||
validity: true,
|
||||
}
|
||||
},
|
||||
>,
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
type JustUnit = ();
|
||||
assert::is_maybe_transmutable::<JustUnit, ()>();
|
||||
//~^ ERROR `JustUnit` cannot be safely transmuted into `JustUnit`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
29
tests/ui/transmutability/type-alias-normalization.stderr
Normal file
29
tests/ui/transmutability/type-alias-normalization.stderr
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
error[E0277]: `JustUnit` cannot be safely transmuted into `JustUnit`
|
||||
--> $DIR/type-alias-normalization.rs:27:37
|
||||
|
|
||||
LL | assert::is_maybe_transmutable::<JustUnit, ()>();
|
||||
| ^^^^^^^^ analyzing the transmutability of `JustUnit` is not yet supported
|
||||
|
|
||||
note: required by a bound in `is_maybe_transmutable`
|
||||
--> $DIR/type-alias-normalization.rs:10:14
|
||||
|
|
||||
LL | pub fn is_maybe_transmutable<Src, Dst>()
|
||||
| --------------------- required by a bound in this function
|
||||
LL | where
|
||||
LL | Src: TransmuteFrom<
|
||||
| ______________^
|
||||
LL | | Src,
|
||||
LL | | {
|
||||
LL | | Assume {
|
||||
... |
|
||||
LL | | },
|
||||
LL | | >,
|
||||
| |_________^ required by this bound in `is_maybe_transmutable`
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn test() where (): TransmuteFrom<(), Assume { alignment: true, lifetimes: true, safety: true, validity: true }> {
|
||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue