-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TransmuteFrom: normalize types, unify confirmation and error reporting
Refactor to share code between `TransmuteFrom`'s trait selection and error reporting code paths. Additionally normalizes the source and destination types, and gracefully handles normalization errors. Fixes #130413
- Loading branch information
Showing
13 changed files
with
161 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use rustc_infer::infer::InferCtxt; | ||
use rustc_infer::traits::{Obligation, ObligationCause}; | ||
use rustc_middle::ty::{Binder, ParamEnv, PolyTraitRef, Ty, TyCtxt}; | ||
use rustc_transmute::layout::rustc::Ref; | ||
use rustc_transmute::{Answer, Assume, Condition, Reason}; | ||
|
||
/// Attempts to confirm the given transmutability candidate. | ||
/// | ||
/// The return type of this routine reflects that it is designed to support the | ||
/// needs of both trait selection and error reporting; it returns: | ||
/// - `Ok(None)` if the types are transmutable | ||
/// - `Ok(Some(src, dst, assumptions, condition))` if the `src` is transmutable | ||
/// into `dst` when `condition` holds under `assumptions` | ||
/// - `Err(None)` if transmutability cannot be assessed; e.g., due to a | ||
/// malformed `Assume` | ||
/// - `Err(Some((src, dst, reason))` if `src` is not transmutable into `dst` | ||
/// because of `reason`. | ||
pub(crate) fn confirm_transmutability_candidate<'tcx, P>( | ||
infcx: &InferCtxt<'tcx>, | ||
obligation: &Obligation<'tcx, P>, | ||
trait_ref: PolyTraitRef<'tcx>, | ||
) -> Result< | ||
Option<(Ty<'tcx>, Ty<'tcx>, Assume, Condition<Ref<'tcx>>)>, | ||
Option<(Ty<'tcx>, Ty<'tcx>, Reason<Ref<'tcx>>)>, | ||
> { | ||
/// Attempts to deeply normalize `ty`. | ||
fn try_normalize<'tcx>( | ||
tcx: TyCtxt<'tcx>, | ||
param_env: ParamEnv<'tcx>, | ||
ty: Binder<'tcx, Ty<'tcx>>, | ||
) -> Option<Binder<'tcx, Ty<'tcx>>> { | ||
use rustc_infer::infer::TyCtxtInferExt; | ||
|
||
use crate::traits::ObligationCtxt; | ||
let infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(); | ||
let ocx = ObligationCtxt::new(&infcx); | ||
let cause = ObligationCause::dummy(); | ||
let Ok(ty) = ocx.deeply_normalize(&cause, param_env, ty) else { return None }; | ||
let errors = ocx.select_all_or_error(); | ||
if errors.is_empty() { Some(ty) } else { None } | ||
} | ||
|
||
let dst = trait_ref.map_bound(|tr| tr.args.type_at(0)); | ||
let src = trait_ref.map_bound(|tr| tr.args.type_at(1)); | ||
|
||
let Some(dst) = try_normalize(infcx.tcx, obligation.param_env, dst) else { | ||
return Err(None); | ||
}; | ||
|
||
let Some(src) = try_normalize(infcx.tcx, obligation.param_env, src) else { | ||
return Err(None); | ||
}; | ||
|
||
// The immediate layouts of `src` and `dst` do not depend on lifetimes. | ||
let dst = dst.skip_binder(); | ||
let src = src.skip_binder(); | ||
|
||
let Some(assume) = rustc_transmute::Assume::from_const( | ||
infcx.tcx, | ||
obligation.param_env, | ||
trait_ref.skip_binder().args.const_at(2), | ||
) else { | ||
return Err(None); | ||
}; | ||
|
||
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(infcx); | ||
let maybe_transmutable = transmute_env.is_transmutable( | ||
obligation.cause.clone(), | ||
rustc_transmute::Types { dst, src }, | ||
assume, | ||
); | ||
|
||
match maybe_transmutable { | ||
Answer::No(reason) => return Err(Some((src, dst, reason))), | ||
Answer::If(cond) => Ok(Some((src, dst, assume, cond))), | ||
Answer::Yes => Ok(None), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#![crate_type = "lib"] | ||
#![feature(transmutability)] | ||
trait Aaa { | ||
type Y; | ||
} | ||
|
||
trait Bbb { | ||
type B: std::mem::TransmuteFrom<()>; | ||
} | ||
|
||
impl<T> Bbb for T | ||
where | ||
T: Aaa, | ||
{ | ||
type B = T::Y; //~ERROR: `()` cannot be safely transmuted into `<T as Aaa>::Y` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error[E0277]: `()` cannot be safely transmuted into `<T as Aaa>::Y` | ||
--> $DIR/assoc-bound.rs:15:14 | ||
| | ||
LL | type B = T::Y; | ||
| ^^^^ `<T as Aaa>::Y` has an unknown layout | ||
| | ||
note: required by a bound in `Bbb::B` | ||
--> $DIR/assoc-bound.rs:8:13 | ||
| | ||
LL | type B: std::mem::TransmuteFrom<()>; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Bbb::B` | ||
help: consider further restricting the associated type | ||
| | ||
LL | T: Aaa, <T as Aaa>::Y: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }> | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0277`. |
4 changes: 2 additions & 2 deletions
4
tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters