about summary refs log tree commit diff
path: root/library/core/src/intrinsics
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-03-22 20:08:01 +0100
committerGitHub <noreply@github.com>2023-03-22 20:08:01 +0100
commit9545ab8e129e0b93baff2a4bfb01f2ce34bea099 (patch)
treec70fa7e8cd332c271842939b3fac1ae219d71d64 /library/core/src/intrinsics
parent56959e5fe33d7e6846aaef544fca8ab548ae733e (diff)
parent9dc275bb54ab088ac85a08dc807984afd57a78c7 (diff)
downloadrust-9545ab8e129e0b93baff2a4bfb01f2ce34bea099.tar.gz
rust-9545ab8e129e0b93baff2a4bfb01f2ce34bea099.zip
Rollup merge of #109392 - cbeuw:composite-ret, r=JakobDegen
Custom MIR: Allow optional RET type annotation

This currently doesn't compile because the type of `RET` is inferred, which fails if RET is a composite type and fields are initialised separately.
```rust
#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn fn0() -> (i32, bool) {
    mir! ({
        RET.0 = 0;
        RET.1 = true;
        Return()
    })
}
```
```
error[E0282]: type annotations needed
 --> src/lib.rs:8:9
  |
8 |         RET.0 = 0;
  |         ^^^ cannot infer type

For more information about this error, try `rustc --explain E0282`.
```

This PR allows the user to manually specify the return type with `type RET = ...;` if required:

```rust
#[custom_mir(dialect = "runtime", phase = "optimized")]
fn fn0() -> (i32, bool) {
    mir! (
        type RET = (i32, bool);
        {
            RET.0 = 0;
            RET.1 = true;
            Return()
        }
    )
}
```

The syntax is not optimal, I'm happy to see other suggestions. Ideally I wanted it to be a normal type annotation like `let RET: ...;`, but this runs into the multiple parsing options error during macro expansion, as it can be parsed as a normal `let` declaration as well.

r? ```@oli-obk``` or ```@tmiasko``` or ```@JakobDegen```
Diffstat (limited to 'library/core/src/intrinsics')
-rw-r--r--library/core/src/intrinsics/mir.rs17
1 files changed, 16 insertions, 1 deletions
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 64fc1c0c277..3061f76df04 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -49,6 +49,8 @@
 //!
 //! The input to the [`mir!`] macro is:
 //!
+//!  - An optional return type annotation in the form of `type RET = ...;`. This may be required
+//!    if the compiler cannot infer the type of RET.
 //!  - A possibly empty list of local declarations. Locals can also be declared inline on
 //!    assignments via `let`. Type inference generally works. Shadowing does not.
 //!  - A list of basic blocks. The first of these is the start block and is where execution begins.
@@ -124,6 +126,18 @@
 //!         }
 //!     )
 //! }
+//!
+//! #[custom_mir(dialect = "runtime", phase = "optimized")]
+//! fn annotated_return_type() -> (i32, bool) {
+//!     mir!(
+//!         type RET = (i32, bool);
+//!         {
+//!             RET.0 = 1;
+//!             RET.1 = true;
+//!             Return()
+//!         }
+//!     )
+//! }
 //! ```
 //!
 //! We can also set off compilation failures that happen in sufficiently late stages of the
@@ -342,6 +356,7 @@ define!(
 #[rustc_macro_transparency = "transparent"]
 pub macro mir {
     (
+        $(type RET = $ret_ty:ty ;)?
         $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
 
         {
@@ -362,7 +377,7 @@ pub macro mir {
         {
             // Now all locals
             #[allow(non_snake_case)]
-            let RET;
+            let RET $(: $ret_ty)?;
             $(
                 let $local_decl $(: $local_decl_ty)? ;
             )*