mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
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.
This commit is contained in:
commit
f5222cdbd3
@ -649,7 +649,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
|
||||
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
|
||||
ObligationCause::dummy(),
|
||||
ty::Binder::dummy(src_and_dst),
|
||||
src_and_dst,
|
||||
scope,
|
||||
assume,
|
||||
) {
|
||||
|
@ -742,7 +742,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
{
|
||||
// Recompute the safe transmute reason and use that for the error reporting
|
||||
self.get_safe_transmute_error_and_reason(
|
||||
trait_predicate,
|
||||
obligation.clone(),
|
||||
trait_ref,
|
||||
span,
|
||||
@ -1629,7 +1628,6 @@ trait InferCtxtPrivExt<'tcx> {
|
||||
|
||||
fn get_safe_transmute_error_and_reason(
|
||||
&self,
|
||||
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
span: Span,
|
||||
@ -2921,18 +2919,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
fn get_safe_transmute_error_and_reason(
|
||||
&self,
|
||||
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
span: Span,
|
||||
) -> (String, Option<String>) {
|
||||
let src_and_dst = trait_predicate.map_bound(|p| rustc_transmute::Types {
|
||||
dst: p.trait_ref.substs.type_at(0),
|
||||
src: p.trait_ref.substs.type_at(1),
|
||||
});
|
||||
let scope = trait_ref.skip_binder().substs.type_at(2);
|
||||
// Erase regions because layout code doesn't particularly care about regions.
|
||||
let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
|
||||
|
||||
let src_and_dst = rustc_transmute::Types {
|
||||
dst: trait_ref.substs.type_at(0),
|
||||
src: trait_ref.substs.type_at(1),
|
||||
};
|
||||
let scope = trait_ref.substs.type_at(2);
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.skip_binder().substs.const_at(3)) else {
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
|
||||
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
|
||||
};
|
||||
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
|
||||
@ -2942,8 +2942,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
assume,
|
||||
) {
|
||||
rustc_transmute::Answer::No(reason) => {
|
||||
let dst = trait_ref.skip_binder().substs.type_at(0);
|
||||
let src = trait_ref.skip_binder().substs.type_at(1);
|
||||
let dst = trait_ref.substs.type_at(0);
|
||||
let src = trait_ref.substs.type_at(1);
|
||||
let custom_err_msg = format!(
|
||||
"`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
|
||||
);
|
||||
|
@ -275,33 +275,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||
debug!(?obligation, "confirm_transmutability_candidate");
|
||||
|
||||
let predicate = obligation.predicate;
|
||||
// We erase regions here because transmutability calls layout queries,
|
||||
// which does not handle inference regions and doesn't particularly
|
||||
// care about other regions. Erasing late-bound regions is equivalent
|
||||
// to instantiating the binder with placeholders then erasing those
|
||||
// placeholder regions.
|
||||
let predicate =
|
||||
self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
|
||||
|
||||
let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
|
||||
let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
|
||||
|
||||
let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
|
||||
dst: p.trait_ref.substs.type_at(0),
|
||||
src: p.trait_ref.substs.type_at(1),
|
||||
});
|
||||
|
||||
let scope = type_at(2).skip_binder();
|
||||
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
||||
let cause = obligation.cause.clone();
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
self.infcx.tcx,
|
||||
obligation.param_env,
|
||||
predicate.trait_ref.substs.const_at(3)
|
||||
) else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
||||
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
|
||||
|
||||
let maybe_transmutable = transmute_env.is_transmutable(cause, src_and_dst, scope, assume);
|
||||
|
||||
use rustc_transmute::Answer;
|
||||
let maybe_transmutable = transmute_env.is_transmutable(
|
||||
obligation.cause.clone(),
|
||||
rustc_transmute::Types {
|
||||
dst: predicate.trait_ref.substs.type_at(0),
|
||||
src: predicate.trait_ref.substs.type_at(1),
|
||||
},
|
||||
predicate.trait_ref.substs.type_at(2),
|
||||
assume,
|
||||
);
|
||||
|
||||
match maybe_transmutable {
|
||||
Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
|
||||
rustc_transmute::Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
|
||||
_ => Err(Unimplemented),
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,6 @@ mod rustc {
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::Binder;
|
||||
use rustc_middle::ty::Const;
|
||||
use rustc_middle::ty::ParamEnv;
|
||||
use rustc_middle::ty::Ty;
|
||||
@ -92,15 +91,13 @@ mod rustc {
|
||||
pub fn is_transmutable(
|
||||
&mut self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
src_and_dst: Binder<'tcx, Types<'tcx>>,
|
||||
types: Types<'tcx>,
|
||||
scope: Ty<'tcx>,
|
||||
assume: crate::Assume,
|
||||
) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
|
||||
let src = src_and_dst.map_bound(|types| types.src).skip_binder();
|
||||
let dst = src_and_dst.map_bound(|types| types.dst).skip_binder();
|
||||
crate::maybe_transmutable::MaybeTransmutableQuery::new(
|
||||
src,
|
||||
dst,
|
||||
types.src,
|
||||
types.dst,
|
||||
scope,
|
||||
assume,
|
||||
self.infcx.tcx,
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`
|
||||
error[E0277]: `&Unit` cannot be safely transmuted into `&Unit` in the defining scope of `assert::Context`
|
||||
--> $DIR/references.rs:29:52
|
||||
|
|
||||
LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
|
||||
| ^^^^^^^^^^^^^ `&'static Unit` does not have a well-specified layout
|
||||
| ^^^^^^^^^^^^^ `&Unit` does not have a well-specified layout
|
||||
|
|
||||
note: required by a bound in `is_maybe_transmutable`
|
||||
--> $DIR/references.rs:16:14
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`
|
||||
error[E0277]: `&Unit` cannot be safely transmuted into `&Unit` in the defining scope of `assert::Context`
|
||||
--> $DIR/references.rs:29:52
|
||||
|
|
||||
LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
|
||||
| ^^^^^^^^^^^^^ `&'static Unit` does not have a well-specified layout
|
||||
| ^^^^^^^^^^^^^ `&Unit` does not have a well-specified layout
|
||||
|
|
||||
note: required by a bound in `is_maybe_transmutable`
|
||||
--> $DIR/references.rs:16:14
|
||||
|
22
tests/ui/transmutability/region-infer.rs
Normal file
22
tests/ui/transmutability/region-infer.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#![feature(transmutability)]
|
||||
|
||||
use std::mem::{Assume, BikeshedIntrinsicFrom};
|
||||
pub struct Context;
|
||||
|
||||
#[repr(C)]
|
||||
struct W<'a>(&'a ());
|
||||
|
||||
fn test<'a>()
|
||||
where
|
||||
W<'a>: BikeshedIntrinsicFrom<
|
||||
(),
|
||||
Context,
|
||||
{ Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
|
||||
>,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test();
|
||||
//~^ ERROR `()` cannot be safely transmuted into `W<'_>`
|
||||
}
|
23
tests/ui/transmutability/region-infer.stderr
Normal file
23
tests/ui/transmutability/region-infer.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error[E0277]: `()` cannot be safely transmuted into `W<'_>` in the defining scope of `Context`
|
||||
--> $DIR/region-infer.rs:20:5
|
||||
|
|
||||
LL | test();
|
||||
| ^^^^ `W<'_>` does not have a well-specified layout
|
||||
|
|
||||
note: required by a bound in `test`
|
||||
--> $DIR/region-infer.rs:11:12
|
||||
|
|
||||
LL | fn test<'a>()
|
||||
| ---- required by a bound in this function
|
||||
LL | where
|
||||
LL | W<'a>: BikeshedIntrinsicFrom<
|
||||
| ____________^
|
||||
LL | | (),
|
||||
LL | | Context,
|
||||
LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
|
||||
LL | | >,
|
||||
| |_________^ required by this bound in `test`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user