Skip to content

Commit f5222cd

Browse files
authored
Rollup merge of #110038 - compiler-errors:infer-regions-in-transmutability, r=lcnr
Erase regions when confirming transmutability candidate Fixes an ICE where we call `layout_of` on a type with infer regions.
2 parents 5546cb6 + f6bfb4b commit f5222cd

File tree

8 files changed

+89
-45
lines changed

8 files changed

+89
-45
lines changed

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
649649
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
650650
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
651651
ObligationCause::dummy(),
652-
ty::Binder::dummy(src_and_dst),
652+
src_and_dst,
653653
scope,
654654
assume,
655655
) {

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
742742
{
743743
// Recompute the safe transmute reason and use that for the error reporting
744744
self.get_safe_transmute_error_and_reason(
745-
trait_predicate,
746745
obligation.clone(),
747746
trait_ref,
748747
span,
@@ -1629,7 +1628,6 @@ trait InferCtxtPrivExt<'tcx> {
16291628

16301629
fn get_safe_transmute_error_and_reason(
16311630
&self,
1632-
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
16331631
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
16341632
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
16351633
span: Span,
@@ -2921,18 +2919,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29212919

29222920
fn get_safe_transmute_error_and_reason(
29232921
&self,
2924-
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
29252922
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
29262923
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
29272924
span: Span,
29282925
) -> (String, Option<String>) {
2929-
let src_and_dst = trait_predicate.map_bound(|p| rustc_transmute::Types {
2930-
dst: p.trait_ref.substs.type_at(0),
2931-
src: p.trait_ref.substs.type_at(1),
2932-
});
2933-
let scope = trait_ref.skip_binder().substs.type_at(2);
2926+
// Erase regions because layout code doesn't particularly care about regions.
2927+
let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
2928+
2929+
let src_and_dst = rustc_transmute::Types {
2930+
dst: trait_ref.substs.type_at(0),
2931+
src: trait_ref.substs.type_at(1),
2932+
};
2933+
let scope = trait_ref.substs.type_at(2);
29342934
let Some(assume) =
2935-
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.skip_binder().substs.const_at(3)) else {
2935+
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
29362936
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
29372937
};
29382938
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
@@ -2942,8 +2942,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29422942
assume,
29432943
) {
29442944
rustc_transmute::Answer::No(reason) => {
2945-
let dst = trait_ref.skip_binder().substs.type_at(0);
2946-
let src = trait_ref.skip_binder().substs.type_at(1);
2945+
let dst = trait_ref.substs.type_at(0);
2946+
let src = trait_ref.substs.type_at(1);
29472947
let custom_err_msg = format!(
29482948
"`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
29492949
);

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+25-23
Original file line numberDiff line numberDiff line change
@@ -275,33 +275,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
275275
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
276276
debug!(?obligation, "confirm_transmutability_candidate");
277277

278-
let predicate = obligation.predicate;
279-
280-
let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
281-
let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
282-
283-
let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
284-
dst: p.trait_ref.substs.type_at(0),
285-
src: p.trait_ref.substs.type_at(1),
286-
});
287-
288-
let scope = type_at(2).skip_binder();
289-
290-
let Some(assume) =
291-
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
292-
return Err(Unimplemented);
293-
};
294-
295-
let cause = obligation.cause.clone();
278+
// We erase regions here because transmutability calls layout queries,
279+
// which does not handle inference regions and doesn't particularly
280+
// care about other regions. Erasing late-bound regions is equivalent
281+
// to instantiating the binder with placeholders then erasing those
282+
// placeholder regions.
283+
let predicate =
284+
self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
285+
286+
let Some(assume) = rustc_transmute::Assume::from_const(
287+
self.infcx.tcx,
288+
obligation.param_env,
289+
predicate.trait_ref.substs.const_at(3)
290+
) else {
291+
return Err(Unimplemented);
292+
};
296293

297294
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
298-
299-
let maybe_transmutable = transmute_env.is_transmutable(cause, src_and_dst, scope, assume);
300-
301-
use rustc_transmute::Answer;
295+
let maybe_transmutable = transmute_env.is_transmutable(
296+
obligation.cause.clone(),
297+
rustc_transmute::Types {
298+
dst: predicate.trait_ref.substs.type_at(0),
299+
src: predicate.trait_ref.substs.type_at(1),
300+
},
301+
predicate.trait_ref.substs.type_at(2),
302+
assume,
303+
);
302304

303305
match maybe_transmutable {
304-
Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
306+
rustc_transmute::Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
305307
_ => Err(Unimplemented),
306308
}
307309
}

compiler/rustc_transmute/src/lib.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ mod rustc {
6464
use rustc_infer::infer::InferCtxt;
6565
use rustc_macros::{TypeFoldable, TypeVisitable};
6666
use rustc_middle::traits::ObligationCause;
67-
use rustc_middle::ty::Binder;
6867
use rustc_middle::ty::Const;
6968
use rustc_middle::ty::ParamEnv;
7069
use rustc_middle::ty::Ty;
@@ -92,15 +91,13 @@ mod rustc {
9291
pub fn is_transmutable(
9392
&mut self,
9493
cause: ObligationCause<'tcx>,
95-
src_and_dst: Binder<'tcx, Types<'tcx>>,
94+
types: Types<'tcx>,
9695
scope: Ty<'tcx>,
9796
assume: crate::Assume,
9897
) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
99-
let src = src_and_dst.map_bound(|types| types.src).skip_binder();
100-
let dst = src_and_dst.map_bound(|types| types.dst).skip_binder();
10198
crate::maybe_transmutable::MaybeTransmutableQuery::new(
102-
src,
103-
dst,
99+
types.src,
100+
types.dst,
104101
scope,
105102
assume,
106103
self.infcx.tcx,

tests/ui/transmutability/references.current.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`
1+
error[E0277]: `&Unit` cannot be safely transmuted into `&Unit` in the defining scope of `assert::Context`
22
--> $DIR/references.rs:29:52
33
|
44
LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
5-
| ^^^^^^^^^^^^^ `&'static Unit` does not have a well-specified layout
5+
| ^^^^^^^^^^^^^ `&Unit` does not have a well-specified layout
66
|
77
note: required by a bound in `is_maybe_transmutable`
88
--> $DIR/references.rs:16:14

tests/ui/transmutability/references.next.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`
1+
error[E0277]: `&Unit` cannot be safely transmuted into `&Unit` in the defining scope of `assert::Context`
22
--> $DIR/references.rs:29:52
33
|
44
LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
5-
| ^^^^^^^^^^^^^ `&'static Unit` does not have a well-specified layout
5+
| ^^^^^^^^^^^^^ `&Unit` does not have a well-specified layout
66
|
77
note: required by a bound in `is_maybe_transmutable`
88
--> $DIR/references.rs:16:14
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(transmutability)]
2+
3+
use std::mem::{Assume, BikeshedIntrinsicFrom};
4+
pub struct Context;
5+
6+
#[repr(C)]
7+
struct W<'a>(&'a ());
8+
9+
fn test<'a>()
10+
where
11+
W<'a>: BikeshedIntrinsicFrom<
12+
(),
13+
Context,
14+
{ Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
15+
>,
16+
{
17+
}
18+
19+
fn main() {
20+
test();
21+
//~^ ERROR `()` cannot be safely transmuted into `W<'_>`
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0277]: `()` cannot be safely transmuted into `W<'_>` in the defining scope of `Context`
2+
--> $DIR/region-infer.rs:20:5
3+
|
4+
LL | test();
5+
| ^^^^ `W<'_>` does not have a well-specified layout
6+
|
7+
note: required by a bound in `test`
8+
--> $DIR/region-infer.rs:11:12
9+
|
10+
LL | fn test<'a>()
11+
| ---- required by a bound in this function
12+
LL | where
13+
LL | W<'a>: BikeshedIntrinsicFrom<
14+
| ____________^
15+
LL | | (),
16+
LL | | Context,
17+
LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
18+
LL | | >,
19+
| |_________^ required by this bound in `test`
20+
21+
error: aborting due to previous error
22+
23+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)