From 643be38cfe269effdc02111677559f74385b1056 Mon Sep 17 00:00:00 2001 From: Ben Blum Date: Wed, 19 Jun 2013 15:53:05 -0400 Subject: [PATCH] Hide the once-move-out privilege for stack fns behind '-Z once-fns' --- src/librustc/driver/session.rs | 55 ++++++++++-------- src/librustc/middle/mem_categorization.rs | 57 +++++++++++-------- .../once-cant-call-twice-on-stack.rs | 1 + src/test/run-pass/once-move-out-on-stack.rs | 1 + 4 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 73e8cfea8ca2..e4cb614c948e 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -45,32 +45,33 @@ pub struct config { float_type: float_ty } -pub static verbose: uint = 1 << 0; -pub static time_passes: uint = 1 << 1; -pub static count_llvm_insns: uint = 1 << 2; -pub static time_llvm_passes: uint = 1 << 3; -pub static trans_stats: uint = 1 << 4; -pub static asm_comments: uint = 1 << 5; -pub static no_verify: uint = 1 << 6; -pub static trace: uint = 1 << 7; -pub static coherence: uint = 1 << 8; -pub static borrowck_stats: uint = 1 << 9; -pub static borrowck_note_pure: uint = 1 << 10; -pub static borrowck_note_loan: uint = 1 << 11; -pub static no_landing_pads: uint = 1 << 12; -pub static debug_llvm: uint = 1 << 13; -pub static count_type_sizes: uint = 1 << 14; -pub static meta_stats: uint = 1 << 15; -pub static no_opt: uint = 1 << 16; +pub static verbose: uint = 1 << 0; +pub static time_passes: uint = 1 << 1; +pub static count_llvm_insns: uint = 1 << 2; +pub static time_llvm_passes: uint = 1 << 3; +pub static trans_stats: uint = 1 << 4; +pub static asm_comments: uint = 1 << 5; +pub static no_verify: uint = 1 << 6; +pub static trace: uint = 1 << 7; +pub static coherence: uint = 1 << 8; +pub static borrowck_stats: uint = 1 << 9; +pub static borrowck_note_pure: uint = 1 << 10; +pub static borrowck_note_loan: uint = 1 << 11; +pub static no_landing_pads: uint = 1 << 12; +pub static debug_llvm: uint = 1 << 13; +pub static count_type_sizes: uint = 1 << 14; +pub static meta_stats: uint = 1 << 15; +pub static no_opt: uint = 1 << 16; pub static no_monomorphic_collapse: uint = 1 << 17; -pub static gc: uint = 1 << 18; -pub static jit: uint = 1 << 19; -pub static debug_info: uint = 1 << 20; -pub static extra_debug_info: uint = 1 << 21; -pub static statik: uint = 1 << 22; -pub static print_link_args: uint = 1 << 23; -pub static no_debug_borrows: uint = 1 << 24; -pub static lint_llvm : uint = 1 << 25; +pub static gc: uint = 1 << 18; +pub static jit: uint = 1 << 19; +pub static debug_info: uint = 1 << 20; +pub static extra_debug_info: uint = 1 << 21; +pub static statik: uint = 1 << 22; +pub static print_link_args: uint = 1 << 23; +pub static no_debug_borrows: uint = 1 << 24; +pub static lint_llvm: uint = 1 << 25; +pub static once_fns: uint = 1 << 26; pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -112,6 +113,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"lint-llvm", ~"Run the LLVM lint pass on the pre-optimization IR", lint_llvm), + (~"once-fns", + ~"Allow 'once fn' closures to deinitialize captured variables", + once_fns), ] } @@ -293,6 +297,7 @@ impl Session_ { pub fn debug_borrows(@self) -> bool { self.opts.optimize == No && !self.debugging_opt(no_debug_borrows) } + pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) } // pointless function, now... pub fn str_of(@self, id: ast::ident) -> @str { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d020cf651a4a..2eedd35c314a 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -497,30 +497,41 @@ impl mem_categorization_ctxt { let ty = ty::node_id_to_type(self.tcx, fn_node_id); match ty::get(ty).sty { ty::ty_closure(ref closure_ty) => { - match (closure_ty.sigil, closure_ty.onceness) { - (ast::BorrowedSigil, ast::Many) => { - let upvar_cmt = - self.cat_def(id, span, expr_ty, *inner); - @cmt_ { - id:id, - span:span, - cat:cat_stack_upvar(upvar_cmt), - mutbl:upvar_cmt.mutbl.inherit(), - ty:upvar_cmt.ty - } + // Decide whether to use implicit reference or by copy/move + // capture for the upvar. This, combined with the onceness, + // determines whether the closure can move out of it. + let var_is_refd = match (closure_ty.sigil, closure_ty.onceness) { + // Many-shot stack closures can never move out. + (ast::BorrowedSigil, ast::Many) => true, + // 1-shot stack closures can move out with "-Z once-fns". + (ast::BorrowedSigil, ast::Once) + if self.tcx.sess.once_fns() => false, + (ast::BorrowedSigil, ast::Once) => true, + // Heap closures always capture by copy/move, and can + // move out iff they are once. + (ast::OwnedSigil, _) | (ast::ManagedSigil, _) => false, + + }; + if var_is_refd { + let upvar_cmt = + self.cat_def(id, span, expr_ty, *inner); + @cmt_ { + id:id, + span:span, + cat:cat_stack_upvar(upvar_cmt), + mutbl:upvar_cmt.mutbl.inherit(), + ty:upvar_cmt.ty } - (ast::BorrowedSigil, ast::Once) | - (ast::OwnedSigil, _) | (ast::ManagedSigil, _) => { - // FIXME #2152 allow mutation of moved upvars - @cmt_ { - id:id, - span:span, - cat:cat_copied_upvar(CopiedUpvar { - upvar_id: upvar_id, - onceness: closure_ty.onceness}), - mutbl:McImmutable, - ty:expr_ty - } + } else { + // FIXME #2152 allow mutation of moved upvars + @cmt_ { + id:id, + span:span, + cat:cat_copied_upvar(CopiedUpvar { + upvar_id: upvar_id, + onceness: closure_ty.onceness}), + mutbl:McImmutable, + ty:expr_ty } } } diff --git a/src/test/compile-fail/once-cant-call-twice-on-stack.rs b/src/test/compile-fail/once-cant-call-twice-on-stack.rs index 7048f1a7a76f..10877be549e2 100644 --- a/src/test/compile-fail/once-cant-call-twice-on-stack.rs +++ b/src/test/compile-fail/once-cant-call-twice-on-stack.rs @@ -11,6 +11,7 @@ // Testing guarantees provided by once functions. // This program would segfault if it were legal. +// compile-flags:-Z once-fns extern mod extra; use extra::arc; use std::util; diff --git a/src/test/run-pass/once-move-out-on-stack.rs b/src/test/run-pass/once-move-out-on-stack.rs index 21e4a3fa4268..fb8a45172943 100644 --- a/src/test/run-pass/once-move-out-on-stack.rs +++ b/src/test/run-pass/once-move-out-on-stack.rs @@ -10,6 +10,7 @@ // Testing guarantees provided by once functions. +// compile-flags:-Z once-fns extern mod extra; use extra::arc; use std::util;