Use ParamEnv::reveal_all in CFI · rust-lang/rust@b0beb64 (original) (raw)
File tree
2 files changed
lines changed
- compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi
2 files changed
lines changed
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -6,7 +6,7 @@ | ||
| 6 | 6 | |
| 7 | 7 | use rustc_data_structures::fx::FxHashMap; |
| 8 | 8 | use rustc_middle::bug; |
| 9 | -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; | |
| 9 | +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; | |
| 10 | 10 | use rustc_target::abi:🤙:{Conv, FnAbi, PassMode}; |
| 11 | 11 | use tracing::instrument; |
| 12 | 12 | |
| @@ -112,11 +112,12 @@ pub fn typeid_for_instance<'tcx>( | ||
| 112 | 112 | instance: Instance<'tcx>, |
| 113 | 113 | options: TypeIdOptions, |
| 114 | 114 | ) -> String { |
| 115 | +assert!(!instance.has_non_region_param(), "{instance:#?} must be fully monomorphic"); | |
| 115 | 116 | let transform_ty_options = TransformTyOptions::from_bits(options.bits()) |
| 116 | 117 | .unwrap_or_else(| |
| 117 | 118 | let instance = transform_instance(tcx, instance, transform_ty_options); |
| 118 | 119 | let fn_abi = tcx |
| 119 | -.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty()))) | |
| 120 | +.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty()))) | |
| 120 | 121 | .unwrap_or_else(|error |
| 121 | 122 | bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}") |
| 122 | 123 | }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| 1 | +//@ needs-sanitizer-cfi | |
| 2 | +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi | |
| 3 | +//@ no-prefer-dynamic | |
| 4 | +//@ only-x86_64-unknown-linux-gnu | |
| 5 | +//@ build-pass | |
| 6 | + | |
| 7 | +// See comment below for why this test exists. | |
| 8 | + | |
| 9 | +trait Tr<U> { | |
| 10 | +type Projection; | |
| 11 | +} | |
| 12 | + | |
| 13 | +impl<F, U> Tr<U> for F | |
| 14 | +where | |
| 15 | +F: Fn() -> U | |
| 16 | +{ | |
| 17 | +type Projection = U; | |
| 18 | +} | |
| 19 | + | |
| 20 | +fn test<B: Tr<U>, U>(b: B) -> B::Projection | |
| 21 | +{ | |
| 22 | +todo!() | |
| 23 | +} | |
| 24 | + | |
| 25 | +fn main() { | |
| 26 | +fn rpit_fn() -> impl Sized {} | |
| 27 | + | |
| 28 | +// When CFI runs, it tries to compute the signature of the call. This | |
| 29 | +// ends up giving us a signature of: | |
| 30 | +// `fn test::<rpit_fn, ()>() -> <rpit_fn as Tr<()>>::Projection`, | |
| 31 | +// where `rpit_fn` is the ZST FnDef for the function. However, we were | |
| 32 | +// previously using a Reveal::UserFacing param-env. This means that the | |
| 33 | +// `<rpit_fn as Tr<()>>::Projection` return type is impossible to normalize, | |
| 34 | +// since it would require proving `rpit_fn: Fn() -> ()`, but we cannot | |
| 35 | +// prove that the `impl Sized` opaque is `()` with a user-facing param-env. | |
| 36 | +// This leads to a normalization error, and then an ICE. | |
| 37 | +// | |
| 38 | +// Side-note: | |
| 39 | +// So why is the second generic of `test` "`()`", and not the | |
| 40 | +// `impl Sized` since we inferred it from the return type of `rpit_fn` | |
| 41 | +// during typeck? Well, that's because we're using the generics from the | |
| 42 | +// terminator of the MIR, which has had the RevealAll pass performed on it. | |
| 43 | +let _ = test(rpit_fn); | |
| 44 | +} |