diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 86f3c7c2e3f..1eb8b0ca406 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -287,9 +287,8 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { type T = stable_mir::mir::Body; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - stable_mir::mir::Body { - blocks: self - .basic_blocks + stable_mir::mir::Body::new( + self.basic_blocks .iter() .map(|block| stable_mir::mir::BasicBlock { terminator: block.terminator().stable(tables), @@ -300,16 +299,15 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { .collect(), }) .collect(), - locals: self - .local_decls + self.local_decls .iter() .map(|decl| stable_mir::mir::LocalDecl { ty: decl.ty.stable(tables), span: decl.source_info.span.stable(tables), }) .collect(), - arg_count: self.arg_count, - } + self.arg_count, + ) } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 34dff7a6214..8cdc9614db6 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -8,14 +8,40 @@ pub struct Body { pub blocks: Vec, /// Declarations of locals. - /// - /// The first local is the return value pointer, followed by `arg_count` - /// locals for the function arguments, followed by any user-declared - /// variables and temporaries. + // + // The first local is the return value pointer, followed by `arg_count` + // locals for the function arguments, followed by any user-declared + // variables and temporaries. pub locals: LocalDecls, - /// The number of arguments this function takes. - pub arg_count: usize, + // The number of arguments this function takes. + arg_count: usize, +} + +impl Body { + /// Constructs a `Body`. + /// + /// A constructor is required to build a `Body` from outside the crate + /// because the `arg_count` field is private. + pub fn new(blocks: Vec, locals: LocalDecls, arg_count: usize) -> Self { + // If locals doesn't contain enough entries, it can lead to panics in + // `ret_local` and `arg_locals`. + assert!( + locals.len() >= arg_count + 1, + "A Body must contain at least a local for the return value and each of the function's arguments" + ); + Self { blocks, locals, arg_count } + } + + /// Gets the function's return local. + pub fn ret_local(&self) -> &LocalDecl { + &self.locals[0] + } + + /// Gets the locals in `self` that correspond to the function's arguments. + pub fn arg_locals(&self) -> &[LocalDecl] { + &self.locals[1..self.arg_count + 1] + } } type LocalDecls = Vec;