From c8c3579bffaeb29b1feae286e06d792293e10287 Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Wed, 23 Nov 2016 14:48:31 -0500 Subject: [PATCH] Fix closure arguments which are immediate because of field reordering. While building immediates goes through type_of::type_of, extracting them must account for field reorderings. --- src/librustc_trans/mir/block.rs | 10 ++++++++-- src/test/run-pass/closure-immediate.rs | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/closure-immediate.rs diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 76f5f32b5dc..fe087bc4951 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -11,7 +11,7 @@ use llvm::{self, ValueRef}; use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err}; use rustc::middle::lang_items; -use rustc::ty; +use rustc::ty::{self, layout}; use rustc::mir; use abi::{Abi, FnType, ArgType}; use adt; @@ -722,8 +722,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } Immediate(llval) => { + let l = bcx.ccx().layout_of(tuple.ty); + let v = if let layout::Univariant { ref variant, .. } = *l { + variant + } else { + bug!("Not a tuple."); + }; for (n, &ty) in arg_types.iter().enumerate() { - let mut elem = bcx.extract_value(llval, n); + let mut elem = bcx.extract_value(llval, v.memory_index[n] as usize); // Truncate bools to i1, if needed if ty.is_bool() && common::val_ty(elem) != Type::i1(bcx.ccx()) { elem = bcx.trunc(elem, Type::i1(bcx.ccx())); diff --git a/src/test/run-pass/closure-immediate.rs b/src/test/run-pass/closure-immediate.rs new file mode 100644 index 00000000000..69aa16c3fb5 --- /dev/null +++ b/src/test/run-pass/closure-immediate.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// After the work to reoptimize structs, it became possible for immediate logic to fail. +// This test verifies that it actually works. + +fn main() { + let c = |a: u8, b: u16, c: u8| { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + }; + c(1, 2, 3); +} \ No newline at end of file