From c82cf470fc0ee75cf5a1e652fca478882d0788e8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 28 Jun 2021 22:16:06 +0300 Subject: [PATCH 1/2] Allow reifying intrinsics to `fn` pointers. --- compiler/rustc_borrowck/src/type_check/mod.rs | 12 ++++++ .../src/infer/error_reporting/mod.rs | 3 -- compiler/rustc_middle/src/ty/error.rs | 3 -- compiler/rustc_middle/src/ty/instance.rs | 4 ++ .../rustc_middle/src/ty/structural_impls.rs | 1 - compiler/rustc_typeck/src/check/cast.rs | 4 -- compiler/rustc_typeck/src/check/coercion.rs | 36 ++++++++++++------ src/test/ui/reify-intrinsic.rs | 37 +++++++++++++------ src/test/ui/reify-intrinsic.stderr | 34 ----------------- .../transmute-different-sizes-reified.rs | 31 ++++++++++++++++ .../transmute-different-sizes-reified.stderr | 30 +++++++++++++++ 11 files changed, 127 insertions(+), 68 deletions(-) delete mode 100644 src/test/ui/reify-intrinsic.stderr create mode 100644 src/test/ui/transmute/transmute-different-sizes-reified.rs create mode 100644 src/test/ui/transmute/transmute-different-sizes-reified.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 55790bd2daa9b..cf0092895b99f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -35,6 +35,7 @@ use rustc_middle::ty::{ use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; +use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; @@ -323,6 +324,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { } } +#[track_caller] fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: &str) { // We sometimes see MIR failures (notably predicate failures) due to // the fact that we check rvalue sized predicates here. So use `delay_span_bug` @@ -2054,6 +2056,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // and hence may contain unnormalized results. let fn_sig = self.normalize(fn_sig, location); + // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify` + // in `rustc_typeck::check::coercion`. + let fn_sig = fn_sig.map_bound(|mut sig| { + if matches!(sig.abi, Abi::RustIntrinsic | Abi::PlatformIntrinsic) { + sig.abi = Abi::Rust; + } + + sig + }); + let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig); if let Err(terr) = self.eq_types( diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c44d4361f037a..a2d8f7e7a583a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2628,9 +2628,6 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => { Error0644("closure/generator type that references itself") } - TypeError::IntrinsicCast => { - Error0308("cannot coerce intrinsics to function pointers") - } TypeError::ObjectUnsafeCoercion(did) => Error0038(*did), _ => Error0308("mismatched types"), }, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 08b4d3aecda0a..9f2c4e539f6c7 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -66,7 +66,6 @@ pub enum TypeError<'tcx> { ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), - IntrinsicCast, /// Safe `#[target_feature]` functions are not assignable to safe function pointers. TargetFeatureCast(DefId), } @@ -197,7 +196,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ConstMismatch(ref values) => { write!(f, "expected `{}`, found `{}`", values.expected, values.found) } - IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"), TargetFeatureCast(_) => write!( f, "cannot coerce functions with `#[target_feature]` to safe function pointers" @@ -229,7 +227,6 @@ impl<'tcx> TypeError<'tcx> { | ProjectionMismatched(_) | ExistentialMismatch(_) | ConstMismatch(_) - | IntrinsicCast | ObjectUnsafeCoercion(_) => true, } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 9b8247fd0283e..b39947943a168 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -394,6 +394,10 @@ impl<'tcx> Instance<'tcx> { debug!(" => fn pointer created for virtual call"); resolved.def = InstanceDef::ReifyShim(def_id); } + InstanceDef::Intrinsic(def_id) => { + debug!(" => fn pointer created for intrinsic call"); + resolved.def = InstanceDef::ReifyShim(def_id); + } _ => {} } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8f343ba9fec22..2b245c576107a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -619,7 +619,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Sorts(x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(x) => return tcx.lift(x).map(ConstMismatch), - IntrinsicCast => IntrinsicCast, TargetFeatureCast(x) => TargetFeatureCast(x), ObjectUnsafeCoercion(x) => return tcx.lift(x).map(ObjectUnsafeCoercion), }) diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 78849b276d6bf..7f8d25e03b9d3 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -38,7 +38,6 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::cast::{CastKind, CastTy}; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_session::lint; @@ -700,9 +699,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { AllowTwoPhase::No, None, ); - if let Err(TypeError::IntrinsicCast) = res { - return Err(CastError::IllegalCast); - } if res.is_err() { return Err(CastError::NonScalar); } diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 07e542b70b90c..72b0fdfa0366d 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -84,6 +84,23 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> { type CoerceResult<'tcx> = InferResult<'tcx, (Vec>, Ty<'tcx>)>; +/// Make any adjustments necessary for a function signature to be compatible +/// with reification to a `fn` pointer. In particular, intrinsics are imported +/// using pseudo-ABIs (`extern "rust-intrinsic" {...}`) currently, but that's +/// an implementation detail and any `fn` pointers that may be taken to them +/// should be indistinguishable from those to regular Rust functions, in order +/// to allow e.g. libcore public APIs to be replaced with intrinsics, without +/// breaking code that was, explicitly or implicitly, creating `fn` pointers. +// FIXME(eddyb) intrinsics shouldn't use pseudo-ABIs, but rather the Rust ABI +// and some other way to indicate that they are intrinsics (e.g. new attributes). +fn prepare_fn_sig_for_reify(mut sig: ty::FnSig<'tcx>) -> ty::FnSig<'tcx> { + if matches!(sig.abi, Abi::RustIntrinsic | Abi::PlatformIntrinsic) { + sig.abi = Abi::Rust; + } + + sig +} + /// Coercing a mutable reference to an immutable works, while /// coercing `&T` to `&mut T` should be forbidden. fn coerce_mutbls<'tcx>( @@ -779,10 +796,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match b.kind() { ty::FnPtr(b_sig) => { let a_sig = a.fn_sig(self.tcx); - // Intrinsics are not coercible to function pointers - if a_sig.abi() == Abi::RustIntrinsic || a_sig.abi() == Abi::PlatformIntrinsic { - return Err(TypeError::IntrinsicCast); - } + + // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`. + let a_sig = a_sig.map_bound(prepare_fn_sig_for_reify); // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). if let ty::FnDef(def_id, _) = *a.kind() { @@ -1043,14 +1059,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { - // Intrinsics are not coercible to function pointers. - if a_sig.abi() == Abi::RustIntrinsic - || a_sig.abi() == Abi::PlatformIntrinsic - || b_sig.abi() == Abi::RustIntrinsic - || b_sig.abi() == Abi::PlatformIntrinsic - { - return Err(TypeError::IntrinsicCast); - } + // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`. + let a_sig = a_sig.map_bound(prepare_fn_sig_for_reify); + let b_sig = b_sig.map_bound(prepare_fn_sig_for_reify); + // The signature must match. let a_sig = self.normalize_associated_types_in(new.span, a_sig); let b_sig = self.normalize_associated_types_in(new.span, b_sig); diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs index 9eb2f724017ed..1be80017f7ab1 100644 --- a/src/test/ui/reify-intrinsic.rs +++ b/src/test/ui/reify-intrinsic.rs @@ -1,23 +1,38 @@ -// check-fail +// run-pass #![feature(core_intrinsics, intrinsics)] -fn a() { - let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; - //~^ ERROR cannot coerce +// NOTE(eddyb) `#[inline(never)]` and returning `fn` pointers from functions is +// done to force codegen (of the reification-to-`fn`-ptr shims around intrinsics). + +#[inline(never)] +fn a() -> unsafe fn(isize) -> usize { + let f: unsafe fn(isize) -> usize = std::mem::transmute; + f } -fn b() { - let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; - //~^ ERROR casting +#[inline(never)] +fn b() -> unsafe fn(isize) -> usize { + let f = std::mem::transmute as unsafe fn(isize) -> usize; + f } -fn c() { - let _ = [ +#[inline(never)] +fn c() -> [fn(bool) -> bool; 2] { + let fs = [ std::intrinsics::likely, std::intrinsics::unlikely, - //~^ ERROR cannot coerce ]; + fs } -fn main() {} +fn main() { + unsafe { + assert_eq!(a()(-1), !0); + assert_eq!(b()(-1), !0); + } + + let [likely_ptr, unlikely_ptr] = c(); + assert!(likely_ptr(true)); + assert!(unlikely_ptr(true)); +} diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr deleted file mode 100644 index dff4ca68d3103..0000000000000 --- a/src/test/ui/reify-intrinsic.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error[E0308]: cannot coerce intrinsics to function pointers - --> $DIR/reify-intrinsic.rs:6:64 - | -LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; - | ------------------------------------------------- ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers - | | - | expected due to this - | - = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` -help: use parentheses to call this function - | -LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute(...); - | +++++ - -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid - --> $DIR/reify-intrinsic.rs:11:13 - | -LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0308]: cannot coerce intrinsics to function pointers - --> $DIR/reify-intrinsic.rs:18:9 - | -LL | std::intrinsics::unlikely, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers - | - = note: expected type `extern "rust-intrinsic" fn(_) -> _ {likely}` - found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0308, E0606. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/transmute/transmute-different-sizes-reified.rs b/src/test/ui/transmute/transmute-different-sizes-reified.rs new file mode 100644 index 0000000000000..b8790e2824b03 --- /dev/null +++ b/src/test/ui/transmute/transmute-different-sizes-reified.rs @@ -0,0 +1,31 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +// Tests that `transmute` cannot be indirectly called on types of different size. + +#![allow(warnings)] +#![feature(specialization)] + +use std::mem::transmute; + +unsafe fn f() { + let _: i8 = (transmute as unsafe fn(_) -> _)(16i16); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +unsafe fn g(x: &T) { + let _: i8 = (transmute as unsafe fn(_) -> _)(x); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +trait Specializable { type Output; } + +impl Specializable for T { + default type Output = u16; +} + +unsafe fn specializable(x: u16) -> ::Output { + (transmute as unsafe fn(_) -> _)(x) + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +fn main() {} diff --git a/src/test/ui/transmute/transmute-different-sizes-reified.stderr b/src/test/ui/transmute/transmute-different-sizes-reified.stderr new file mode 100644 index 0000000000000..bde5da74ee7db --- /dev/null +++ b/src/test/ui/transmute/transmute-different-sizes-reified.stderr @@ -0,0 +1,30 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes-reified.rs:11:18 + | +LL | let _: i8 = (transmute as unsafe fn(_) -> _)(16i16); + | ^^^^^^^^^ + | + = note: source type: `i16` (N bits) + = note: target type: `i8` (N bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes-reified.rs:16:18 + | +LL | let _: i8 = (transmute as unsafe fn(_) -> _)(x); + | ^^^^^^^^^ + | + = note: source type: `&T` (N bits) + = note: target type: `i8` (N bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes-reified.rs:27:6 + | +LL | (transmute as unsafe fn(_) -> _)(x) + | ^^^^^^^^^ + | + = note: source type: `u16` (N bits) + = note: target type: `::Output` (this type does not have a fixed size) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0512`. From fddc321087e9df051d0e5ef81e091c555e42a1ca Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 15 Jul 2021 12:44:49 +0300 Subject: [PATCH 2/2] rustc_mir: run the lower_intrinsics pass on MIR shims. --- compiler/rustc_mir_transform/src/shim.rs | 5 ++-- ...#1-discriminant_value.LowerIntrinsics.diff | 24 +++++++++++++++++++ ....intrinsics-#1-forget.LowerIntrinsics.diff | 24 +++++++++++++++++++ ...intrinsics-#1-size_of.LowerIntrinsics.diff | 24 +++++++++++++++++++ ...insics-#1-unreachable.LowerIntrinsics.diff | 23 ++++++++++++++++++ ...nsics-#1-wrapping_add.LowerIntrinsics.diff | 24 +++++++++++++++++++ src/test/mir-opt/lower_intrinsics.rs | 17 +++++++++++++ 7 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-discriminant_value.LowerIntrinsics.diff create mode 100644 src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-forget.LowerIntrinsics.diff create mode 100644 src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-size_of.LowerIntrinsics.diff create mode 100644 src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-unreachable.LowerIntrinsics.diff create mode 100644 src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-wrapping_add.LowerIntrinsics.diff diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f2ea5fedc625c..cbaeeaf572916 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -17,8 +17,8 @@ use std::iter; use crate::util::expand_aggregate; use crate::{ - abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads, - run_passes, simplify, + abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, lower_intrinsics, + remove_noop_landing_pads, run_passes, simplify, }; use rustc_middle::mir::patch::MirPatch; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; @@ -82,6 +82,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' &[&[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &remove_noop_landing_pads::RemoveNoopLandingPads, + &lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, diff --git a/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-discriminant_value.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-discriminant_value.LowerIntrinsics.diff new file mode 100644 index 0000000000000..a197e27fd9223 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-discriminant_value.LowerIntrinsics.diff @@ -0,0 +1,24 @@ +- // MIR for `discriminant_value` before LowerIntrinsics ++ // MIR for `discriminant_value` after LowerIntrinsics + + fn discriminant_value(_1: &T) -> ::Discriminant { + let mut _0: ::Discriminant; // return place in scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + + bb0: { +- _0 = discriminant_value::(move _1) -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // mir::Constant +- // + span: $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } ++ _0 = discriminant((*_1)); // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ goto -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb2 (cleanup): { + resume; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-forget.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-forget.LowerIntrinsics.diff new file mode 100644 index 0000000000000..2250c87ff0027 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-forget.LowerIntrinsics.diff @@ -0,0 +1,24 @@ +- // MIR for `std::intrinsics::forget` before LowerIntrinsics ++ // MIR for `std::intrinsics::forget` after LowerIntrinsics + + fn std::intrinsics::forget(_1: T) -> () { + let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + + bb0: { +- _0 = std::intrinsics::forget::(move _1) -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // mir::Constant +- // + span: $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::}, val: Value(Scalar()) } ++ _0 = const (); // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ goto -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb2 (cleanup): { + resume; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-size_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-size_of.LowerIntrinsics.diff new file mode 100644 index 0000000000000..6f95f1c113038 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-size_of.LowerIntrinsics.diff @@ -0,0 +1,24 @@ +- // MIR for `std::intrinsics::size_of` before LowerIntrinsics ++ // MIR for `std::intrinsics::size_of` after LowerIntrinsics + + fn std::intrinsics::size_of() -> usize { + let mut _0: usize; // return place in scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + + bb0: { +- _0 = std::intrinsics::size_of::() -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // mir::Constant +- // + span: $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}, val: Value(Scalar()) } ++ _0 = SizeOf(T); // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ goto -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb2 (cleanup): { + resume; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-unreachable.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-unreachable.LowerIntrinsics.diff new file mode 100644 index 0000000000000..3a7f8656e4d6d --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-unreachable.LowerIntrinsics.diff @@ -0,0 +1,23 @@ +- // MIR for `std::intrinsics::unreachable` before LowerIntrinsics ++ // MIR for `std::intrinsics::unreachable` after LowerIntrinsics + + fn std::intrinsics::unreachable() -> ! { + let mut _0: !; // return place in scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + + bb0: { +- _0 = std::intrinsics::unreachable() -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // mir::Constant +- // + span: $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar()) } ++ unreachable; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb2 (cleanup): { + resume; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-wrapping_add.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-wrapping_add.LowerIntrinsics.diff new file mode 100644 index 0000000000000..c03699a42951a --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.core.intrinsics-#1-wrapping_add.LowerIntrinsics.diff @@ -0,0 +1,24 @@ +- // MIR for `wrapping_add` before LowerIntrinsics ++ // MIR for `wrapping_add` after LowerIntrinsics + + fn wrapping_add(_1: T, _2: T) -> T { + let mut _0: T; // return place in scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + + bb0: { +- _0 = wrapping_add::(move _1, move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // mir::Constant +- // + span: $SRC_DIR/core/src/intrinsics.rs:LL:COL +- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {std::intrinsics::wrapping_add::}, val: Value(Scalar()) } ++ _0 = Add(move _1, move _2); // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ goto -> bb1; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb1: { + return; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + + bb2 (cleanup): { + resume; // scope 0 at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.rs b/src/test/mir-opt/lower_intrinsics.rs index 8a8880dad02e5..0e27371ac9aa2 100644 --- a/src/test/mir-opt/lower_intrinsics.rs +++ b/src/test/mir-opt/lower_intrinsics.rs @@ -76,3 +76,20 @@ pub fn discriminant(t: T) { core::intrinsics::discriminant_value(&()); core::intrinsics::discriminant_value(&E::B); } + +// Check that the MIR shims used for reifying intrinsics to `fn` pointers, +// also go through the lowering pass. +pub fn reify_intrinsics() -> impl Copy { + ( +// EMIT_MIR core.intrinsics-#1-wrapping_add.LowerIntrinsics.diff + core::intrinsics::wrapping_add:: as unsafe fn(_, _) -> _, +// EMIT_MIR core.intrinsics-#1-size_of.LowerIntrinsics.diff + core::intrinsics::size_of:: as unsafe fn() -> _, +// EMIT_MIR core.intrinsics-#1-unreachable.LowerIntrinsics.diff + core::intrinsics::unreachable as unsafe fn() -> !, +// EMIT_MIR core.intrinsics-#1-forget.LowerIntrinsics.diff + core::intrinsics::forget:: as unsafe fn(_), +// EMIT_MIR core.intrinsics-#1-discriminant_value.LowerIntrinsics.diff + core::intrinsics::discriminant_value:: as unsafe fn(_) -> _, + ) +}