about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-04-10 16:15:23 +0200
committerGitHub <noreply@github.com>2024-04-10 16:15:23 +0200
commit2b4c581ef91c5bfe8fdcdf95a1e64b715416fcf3 (patch)
treec7ef0421c6e0f47d1836bb61768366783b897b8d /compiler
parent38af5f9ee8fe422fa8305c052e43c13dff844539 (diff)
parent1cbe92716f0f0f9f15ff890773fad5ffcf534311 (diff)
downloadrust-2b4c581ef91c5bfe8fdcdf95a1e64b715416fcf3.tar.gz
rust-2b4c581ef91c5bfe8fdcdf95a1e64b715416fcf3.zip
Rollup merge of #123659 - celinval:smir-fix-intrinsic, r=oli-obk
Add support to intrinsics fallback body

Before this fix, the call to `body()` would crash, since `has_body()` would return true, but we would try to retrieve the body of an intrinsic which is not allowed.

Instead, the `Instance::body()` function will now convert an Intrinsic into an Item before retrieving its body.

Note: I also changed how we monomorphize the instance body. Unfortunately, the call still ICE for some shims.

r? `@oli-obk`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_smir/src/rustc_smir/builder.rs60
-rw-r--r--compiler/stable_mir/src/mir/mono.rs11
2 files changed, 37 insertions, 34 deletions
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
index 0762016ef75..221224eed01 100644
--- a/compiler/rustc_smir/src/rustc_smir/builder.rs
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -4,9 +4,10 @@
 //! monomorphic body using internal representation.
 //! After that, we convert the internal representation into a stable one.
 use crate::rustc_smir::{Stable, Tables};
+use rustc_hir::def::DefKind;
 use rustc_middle::mir;
 use rustc_middle::mir::visit::MutVisitor;
-use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 
 /// Builds a monomorphic body for a given instance.
 pub struct BodyBuilder<'tcx> {
@@ -16,46 +17,43 @@ pub struct BodyBuilder<'tcx> {
 
 impl<'tcx> BodyBuilder<'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
+        let instance = match instance.def {
+            // To get the fallback body of an intrinsic, we need to convert it to an item.
+            ty::InstanceDef::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
+            _ => instance,
+        };
         BodyBuilder { tcx, instance }
     }
 
     /// Build a stable monomorphic body for a given instance based on the MIR body.
     ///
-    /// Note that we skip instantiation for static and constants. Trying to do so can cause ICE.
-    ///
-    /// We do monomorphize non-generic functions to eval unevaluated constants.
+    /// All constants are also evaluated.
     pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
-        let mut body = self.tcx.instance_mir(self.instance.def).clone();
-        if self.tcx.def_kind(self.instance.def_id()).is_fn_like() || !self.instance.args.is_empty()
+        let body = tables.tcx.instance_mir(self.instance.def).clone();
+        let mono_body = if !self.instance.args.is_empty()
+            // Without the `generic_const_exprs` feature gate, anon consts in signatures do not
+            // get generic parameters. Which is wrong, but also not a problem without
+            // generic_const_exprs
+            || self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
         {
-            self.visit_body(&mut body);
-        }
-        body.stable(tables)
-    }
-
-    fn monomorphize<T>(&self, value: T) -> T
-    where
-        T: ty::TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.instance.instantiate_mir_and_normalize_erasing_regions(
-            self.tcx,
-            ty::ParamEnv::reveal_all(),
-            ty::EarlyBinder::bind(value),
-        )
+            let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
+                tables.tcx,
+                ty::ParamEnv::reveal_all(),
+                ty::EarlyBinder::bind(body),
+            );
+            self.visit_body(&mut mono_body);
+            mono_body
+        } else {
+            // Already monomorphic.
+            body
+        };
+        mono_body.stable(tables)
     }
 }
 
 impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
-    fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, _location: mir::Location) {
-        *ct = self.monomorphize(*ct);
-    }
-
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: mir::visit::TyContext) {
-        *ty = self.monomorphize(*ty);
-    }
-
     fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
-        let const_ = self.monomorphize(constant.const_);
+        let const_ = constant.const_;
         let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
             Ok(v) => v,
             Err(mir::interpret::ErrorHandled::Reported(..)) => return,
@@ -68,10 +66,6 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
         self.super_constant(constant, location);
     }
 
-    fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, _: mir::Location) {
-        *args = self.monomorphize(*args);
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index aafa89c03e0..a032a180fcf 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -41,13 +41,22 @@ impl Instance {
         with(|cx| cx.instance_args(self.def))
     }
 
-    /// Get the body of an Instance. The body will be eagerly monomorphized.
+    /// Get the body of an Instance.
+    ///
+    /// The body will be eagerly monomorphized and all constants will already be evaluated.
+    ///
+    /// This method will return the intrinsic fallback body if one was defined.
     pub fn body(&self) -> Option<Body> {
         with(|context| context.instance_body(self.def))
     }
 
     /// Check whether this instance has a body available.
     ///
+    /// For intrinsics with fallback body, this will return `true`. It is up to the user to decide
+    /// whether to specialize the intrinsic or to use its fallback body.
+    ///
+    /// For more information on fallback body, see <https://github.com/rust-lang/rust/issues/93145>.
+    ///
     /// This call is much cheaper than `instance.body().is_some()`, since it doesn't try to build
     /// the StableMIR body.
     pub fn has_body(&self) -> bool {