about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-06-19 15:53:05 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-06-19 15:53:05 -0400
commit643be38cfe269effdc02111677559f74385b1056 (patch)
tree115d2c06f4010fa7daf36d9fa5050b933cb5cba0 /src
parentc1f037e6ac75e05e6bc3f05ec6cab9de8c971e81 (diff)
downloadrust-643be38cfe269effdc02111677559f74385b1056.tar.gz
rust-643be38cfe269effdc02111677559f74385b1056.zip
Hide the once-move-out privilege for stack fns behind '-Z once-fns'
Diffstat (limited to 'src')
-rw-r--r--src/librustc/driver/session.rs55
-rw-r--r--src/librustc/middle/mem_categorization.rs57
-rw-r--r--src/test/compile-fail/once-cant-call-twice-on-stack.rs1
-rw-r--r--src/test/run-pass/once-move-out-on-stack.rs1
4 files changed, 66 insertions, 48 deletions
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 73e8cfea8ca..e4cb614c948 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 d020cf651a4..2eedd35c314 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 7048f1a7a76..10877be549e 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 21e4a3fa426..fb8a4517294 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;