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```
This commit is contained in:
commit
9545ab8e12
@ -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 @@ fn __internal_make_place<T>(place: T) -> *mut T
|
||||
#[rustc_macro_transparency = "transparent"]
|
||||
pub macro mir {
|
||||
(
|
||||
$(type RET = $ret_ty:ty ;)?
|
||||
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
|
||||
|
||||
{
|
||||
@ -362,7 +377,7 @@ fn __internal_make_place<T>(place: T) -> *mut T
|
||||
{
|
||||
// Now all locals
|
||||
#[allow(non_snake_case)]
|
||||
let RET;
|
||||
let RET $(: $ret_ty)?;
|
||||
$(
|
||||
let $local_decl $(: $local_decl_ty)? ;
|
||||
)*
|
||||
|
21
tests/mir-opt/building/custom/composite_return.rs
Normal file
21
tests/mir-opt/building/custom/composite_return.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
|
||||
// EMIT_MIR composite_return.tuple.built.after.mir
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn tuple() -> (i32, bool) {
|
||||
mir!(
|
||||
type RET = (i32, bool);
|
||||
{
|
||||
RET.0 = 1;
|
||||
RET.1 = true;
|
||||
Return()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(tuple(), (1, true));
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
// MIR for `tuple` after built
|
||||
|
||||
fn tuple() -> (i32, bool) {
|
||||
let mut _0: (i32, bool); // return place in scope 0 at $DIR/composite_return.rs:+0:15: +0:26
|
||||
|
||||
bb0: {
|
||||
(_0.0: i32) = const 1_i32; // scope 0 at $DIR/composite_return.rs:+4:13: +4:22
|
||||
(_0.1: bool) = const true; // scope 0 at $DIR/composite_return.rs:+5:13: +5:25
|
||||
return; // scope 0 at $DIR/composite_return.rs:+6:13: +6:21
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user