From c3c72239b7130b947deb6272c6d0c05872697d91 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Thu, 6 Nov 2014 20:40:32 -0800 Subject: [PATCH 1/2] Remove incorrect assert in trans As an optimization, once unboxed closures receive their environment by value if it fits within the size of an `int`. An assert in this code path assumed that this would only occur if the environment had no more than a single free variable in it, but multiple smaller free variables can easily be packed into the space of an `int`, particularly if any of them are 0-sized. The assert can simply be removed. Closes #18652 --- src/librustc/middle/trans/closure.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 16db4daba46b8..4f6d4ab6a2432 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -322,7 +322,6 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( self_type, "unboxed_closure_env"); store_ty(bcx, bcx.fcx.llenv.unwrap(), datum.val, self_type); - assert!(freevars.len() <= 1); datum.val } else { bcx.fcx.llenv.unwrap() From 2c956d0abfa8cc169fc2c2ab5343b77b20397817 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Thu, 6 Nov 2014 20:44:08 -0800 Subject: [PATCH 2/2] Add regression test for #18652 --- src/test/run-pass/issue-18652.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/run-pass/issue-18652.rs diff --git a/src/test/run-pass/issue-18652.rs b/src/test/run-pass/issue-18652.rs new file mode 100644 index 0000000000000..5ca091000608b --- /dev/null +++ b/src/test/run-pass/issue-18652.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +// Tests multiple free variables being passed by value into an unboxed +// once closure as an optimization by trans. This used to hit an +// incorrect assert. + +#![feature(unboxed_closures, overloaded_calls)] + +fn main() { + let x = 2u8; + let y = 3u8; + assert_eq!((move |:| x + y)(), 5); +}