diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 70b0b810c6c4..f236c4ebb977 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -93,6 +93,12 @@ pub struct Mir<'tcx> { /// the first argument is either the closure or a reference to it. pub upvar_decls: Vec, + /// A boolean indicating whether the last argument (which must be a tuple) + /// is passed as its individual components at the LLVM level. + /// + /// This is used for the "rust-call" ABI. + pub spread_last_arg: bool, + /// A span representing this MIR, for error reporting pub span: Span, @@ -123,6 +129,7 @@ impl<'tcx> Mir<'tcx> { arg_decls: arg_decls, temp_decls: temp_decls, upvar_decls: upvar_decls, + spread_last_arg: false, span: span, cache: Cache::new() } @@ -341,10 +348,6 @@ pub struct TempDecl<'tcx> { pub struct ArgDecl<'tcx> { pub ty: Ty<'tcx>, - /// If true, this argument is a tuple after monomorphization, - /// and has to be collected from multiple actual arguments. - pub spread: bool, - /// Either keywords::Invalid or the name of a single-binding /// pattern associated with this argument. Useful for debuginfo. pub debug_name: Name diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2c58d35973e7..bd42eb3211a8 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -665,7 +665,6 @@ macro_rules! make_mir_visitor { arg_decl: & $($mutability)* ArgDecl<'tcx>) { let ArgDecl { ref $($mutability)* ty, - spread: _, debug_name: _ } = *arg_decl; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 23591f05b877..1f8dffe58717 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -169,7 +169,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, tcx.region_maps.lookup_code_extent( CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id }); let mut block = START_BLOCK; - let mut arg_decls = unpack!(block = builder.in_scope(call_site_extent, block, |builder| { + let arg_decls = unpack!(block = builder.in_scope(call_site_extent, block, |builder| { let arg_decls = unpack!(block = builder.in_scope(arg_extent, block, |builder| { builder.args_and_body(block, return_ty, arguments, arg_extent, ast_block) })); @@ -184,12 +184,11 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, })); assert_eq!(block, builder.return_block()); + let mut spread_last_arg = false; match tcx.node_id_to_type(fn_id).sty { ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => { // RustCall pseudo-ABI untuples the last argument. - if let Some(last_arg) = arg_decls.last() { - arg_decls[last_arg].spread = true; - } + spread_last_arg = true; } _ => {} } @@ -218,7 +217,9 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, }).collect() }); - builder.finish(upvar_decls, arg_decls, return_ty) + let (mut mir, aux) = builder.finish(upvar_decls, arg_decls, return_ty); + mir.spread_last_arg = spread_last_arg; + (mir, aux) } pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, @@ -331,7 +332,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ArgDecl { ty: ty, - spread: false, debug_name: name } }).collect(); diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 1934f7b870d1..efbab3a3b4dc 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -349,7 +349,7 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| { let arg_ty = bcx.monomorphize(&arg_decl.ty); let local = mir.local_index(&mir::Lvalue::Arg(mir::Arg::new(arg_index))).unwrap(); - if arg_decl.spread { + if mir.spread_last_arg && arg_index == mir.arg_decls.len() - 1 { // This argument (e.g. the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple