Skip to content

Commit a257fb9

Browse files
committed
Fix ICE in transmutability error reporting when type aliases are normalized
1 parent 370143f commit a257fb9

File tree

3 files changed

+114
-2
lines changed

3 files changed

+114
-2
lines changed

‎compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs‎

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
254254
LangItem::TransmuteTrait,
255255
) {
256256
// Recompute the safe transmute reason and use that for the error reporting
257+
let (report_obligation, report_pred) =
258+
self.select_transmute_obligation_for_reporting(
259+
&obligation,
260+
main_trait_predicate,
261+
root_obligation,
262+
);
263+
257264
match self.get_safe_transmute_error_and_reason(
258-
obligation.clone(),
259-
main_trait_predicate,
265+
report_obligation,
266+
report_pred,
260267
span,
261268
) {
262269
GetSafeTransmuteErrorAndReason::Silent => {
@@ -2793,6 +2800,51 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27932800
})
27942801
}
27952802

2803+
fn select_transmute_obligation_for_reporting(
2804+
&self,
2805+
obligation: &PredicateObligation<'tcx>,
2806+
trait_predicate: ty::PolyTraitPredicate<'tcx>,
2807+
root_obligation: &PredicateObligation<'tcx>,
2808+
) -> (PredicateObligation<'tcx>, ty::PolyTraitPredicate<'tcx>) {
2809+
let ocx = ObligationCtxt::new(self);
2810+
let normalized_predicate = self.tcx.erase_and_anonymize_regions(
2811+
self.tcx.instantiate_bound_regions_with_erased(trait_predicate),
2812+
);
2813+
let trait_ref = normalized_predicate.trait_ref;
2814+
2815+
let Ok(assume) = ocx.structurally_normalize_const(
2816+
&obligation.cause,
2817+
obligation.param_env,
2818+
trait_ref.args.const_at(2),
2819+
) else {
2820+
return (obligation.clone(), trait_predicate);
2821+
};
2822+
2823+
let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else {
2824+
return (obligation.clone(), trait_predicate);
2825+
};
2826+
2827+
let is_normalized_yes = matches!(
2828+
rustc_transmute::TransmuteTypeEnv::new(self.tcx).is_transmutable(
2829+
trait_ref.args.type_at(1),
2830+
trait_ref.args.type_at(0),
2831+
assume,
2832+
),
2833+
rustc_transmute::Answer::Yes,
2834+
);
2835+
2836+
// If the normalized check unexpectedly passes, fall back to root obligation for reporting.
2837+
if is_normalized_yes
2838+
&& let ty::PredicateKind::Clause(ty::ClauseKind::Trait(root_pred)) =
2839+
root_obligation.predicate.kind().skip_binder()
2840+
&& root_pred.def_id() == trait_predicate.def_id()
2841+
{
2842+
return (root_obligation.clone(), root_obligation.predicate.kind().rebind(root_pred));
2843+
}
2844+
2845+
(obligation.clone(), trait_predicate)
2846+
}
2847+
27962848
fn get_safe_transmute_error_and_reason(
27972849
&self,
27982850
obligation: PredicateObligation<'tcx>,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//! regression test for https://github.com/rust-lang/rust/issues/151462
2+
//@compile-flags: -Znext-solver=globally
3+
#![feature(lazy_type_alias, transmutability)]
4+
#![allow(incomplete_features)]
5+
mod assert {
6+
use std::mem::{Assume, TransmuteFrom};
7+
8+
pub fn is_maybe_transmutable<Src, Dst>()
9+
where
10+
Src: TransmuteFrom<
11+
Src,
12+
{
13+
Assume {
14+
alignment: true,
15+
lifetimes: true,
16+
safety: true,
17+
validity: true,
18+
}
19+
},
20+
>,
21+
{
22+
}
23+
}
24+
25+
fn test() {
26+
type JustUnit = ();
27+
assert::is_maybe_transmutable::<JustUnit, ()>();
28+
//~^ ERROR `JustUnit` cannot be safely transmuted into `JustUnit`
29+
}
30+
31+
fn main() {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0277]: `JustUnit` cannot be safely transmuted into `JustUnit`
2+
--> $DIR/type-alias-normalization.rs:27:37
3+
|
4+
LL | assert::is_maybe_transmutable::<JustUnit, ()>();
5+
| ^^^^^^^^ analyzing the transmutability of `JustUnit` is not yet supported
6+
|
7+
note: required by a bound in `is_maybe_transmutable`
8+
--> $DIR/type-alias-normalization.rs:10:14
9+
|
10+
LL | pub fn is_maybe_transmutable<Src, Dst>()
11+
| --------------------- required by a bound in this function
12+
LL | where
13+
LL | Src: TransmuteFrom<
14+
| ______________^
15+
LL | | Src,
16+
LL | | {
17+
LL | | Assume {
18+
... |
19+
LL | | },
20+
LL | | >,
21+
| |_________^ required by this bound in `is_maybe_transmutable`
22+
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
23+
|
24+
LL | fn test() where (): TransmuteFrom<(), Assume { alignment: true, lifetimes: true, safety: true, validity: true }> {
25+
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26+
27+
error: aborting due to 1 previous error
28+
29+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)