about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-11-20 12:12:38 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-14 04:21:56 -0500
commit698db04a8d44df3d2805b25b9b461a886b9933cd (patch)
tree1baefd7e47d994010720d65046651997f5b0895b /src
parentd61338172fa110fcf9e5f2df0e1e83635d0fde3f (diff)
downloadrust-698db04a8d44df3d2805b25b9b461a886b9933cd.tar.gz
rust-698db04a8d44df3d2805b25b9b461a886b9933cd.zip
Purge the hack that allows `FnOnce` to be used with a by-value self method. Besides being yucky, it will cause problems if we try to make all traits implement themselves, which would make a lot of things in life easier. Also, it was inextricably linked to `Box`, which was not the intention. We can work around its absence, so better to reimplement it later in a more thorough fashion.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/trans/callee.rs150
-rw-r--r--src/librustc_trans/trans/meth.rs71
-rw-r--r--src/librustc_typeck/check/method/probe.rs17
-rw-r--r--src/librustc_typeck/check/vtable.rs8
-rw-r--r--src/test/run-pass/issue-16739.rs26
-rw-r--r--src/test/run-pass/issue-18883.rs19
-rw-r--r--src/test/run-pass/unboxed-closures-monomorphization.rs22
-rw-r--r--src/test/run-pass/unboxed-closures-prelude.rs13
-rw-r--r--src/test/run-pass/unboxed-closures-unboxing-shim.rs19
9 files changed, 42 insertions, 303 deletions
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index b8b2395dde1..67e1735d9a3 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -19,8 +19,7 @@ pub use self::CalleeData::*;
 pub use self::CallArgs::*;
 
 use arena::TypedArena;
-use back::abi;
-use back::link;
+use back::{abi,link};
 use session;
 use llvm::{ValueRef, get_param};
 use llvm;
@@ -357,153 +356,6 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     llfn
 }
 
-/// Translates the adapter that deconstructs a `Box<Trait>` object into
-/// `Trait` so that a by-value self method can be called.
-pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       llshimmedfn: ValueRef,
-                                       fty: &ty::BareFnTy<'tcx>,
-                                       method_id: ast::DefId,
-                                       substs: &subst::Substs<'tcx>)
-                                       -> ValueRef {
-    let _icx = push_ctxt("trans_unboxing_shim");
-    let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
-
-    let fty = fty.subst(tcx, substs);
-
-    // Transform the self type to `Box<self_type>`.
-    let self_type = fty.sig.inputs[0];
-    let boxed_self_type = ty::mk_uniq(tcx, self_type);
-    let boxed_function_type = ty::FnSig {
-        inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
-            if i == 0 {
-                boxed_self_type
-            } else {
-                *typ
-            }
-        }).collect(),
-        output: fty.sig.output,
-        variadic: false,
-    };
-    let boxed_function_type = ty::BareFnTy {
-        fn_style: fty.fn_style,
-        abi: fty.abi,
-        sig: boxed_function_type,
-    };
-    let boxed_function_type = ty::mk_bare_fn(tcx, boxed_function_type);
-    let function_type = match fty.abi {
-        synabi::RustCall => {
-            // We're passing through to a RustCall ABI function, but
-            // because the shim will already perform untupling, we
-            // need to pretend the shimmed function does not use
-            // RustCall so the untupled arguments can be passed
-            // through verbatim.  This is kind of ugly.
-            let fake_ty = ty::FnSig {
-                inputs: type_of::untuple_arguments_if_necessary(ccx,
-                                                                fty.sig.inputs.as_slice(),
-                                                                fty.abi),
-                output: fty.sig.output,
-                variadic: false,
-            };
-            let fake_ty = ty::BareFnTy {
-                fn_style: fty.fn_style,
-                abi: synabi::Rust,
-                sig: fake_ty,
-            };
-            ty::mk_bare_fn(tcx, fake_ty)
-        }
-        _ => {
-            ty::mk_bare_fn(tcx, fty)
-        }
-    };
-
-    let function_name = ty::with_path(tcx, method_id, |path| {
-        link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
-    });
-    let llfn = decl_internal_rust_fn(ccx,
-                                     boxed_function_type,
-                                     function_name.as_slice());
-
-    let block_arena = TypedArena::new();
-    let empty_param_substs = Substs::trans_empty();
-    let return_type = ty::ty_fn_ret(boxed_function_type);
-    let fcx = new_fn_ctxt(ccx,
-                          llfn,
-                          ast::DUMMY_NODE_ID,
-                          false,
-                          return_type,
-                          &empty_param_substs,
-                          None,
-                          &block_arena);
-    let mut bcx = init_function(&fcx, false, return_type);
-
-    // Create the substituted versions of the self type.
-    let arg_scope = fcx.push_custom_cleanup_scope();
-    let arg_scope_id = cleanup::CustomScope(arg_scope);
-    let boxed_self_type = ty::ty_fn_args(boxed_function_type)[0];
-    let arg_types = ty::ty_fn_args(function_type);
-    let self_type = arg_types[0];
-    let boxed_self_kind = arg_kind(&fcx, boxed_self_type);
-
-    // Create a datum for self.
-    let llboxedself = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
-    let llboxedself = Datum::new(llboxedself,
-                                 boxed_self_type,
-                                 boxed_self_kind);
-    let boxed_self =
-        unpack_datum!(bcx,
-                      llboxedself.to_lvalue_datum_in_scope(bcx,
-                                                           "boxedself",
-                                                           arg_scope_id));
-
-    // This `Load` is needed because lvalue data are always by-ref.
-    let llboxedself = Load(bcx, boxed_self.val);
-
-    let llself = if type_is_immediate(ccx, self_type) {
-        let llboxedself = Load(bcx, llboxedself);
-        immediate_rvalue(llboxedself, self_type)
-    } else {
-        let llself = rvalue_scratch_datum(bcx, self_type, "self");
-        memcpy_ty(bcx, llself.val, llboxedself, self_type);
-        llself
-    };
-
-    // Make sure we don't free the box twice!
-    boxed_self.kind.post_store(bcx, boxed_self.val, boxed_self_type);
-
-    // Schedule a cleanup to free the box.
-    fcx.schedule_free_value(arg_scope_id,
-                            llboxedself,
-                            cleanup::HeapExchange,
-                            self_type);
-
-    // Now call the function.
-    let mut llshimmedargs = vec!(llself.val);
-    for i in range(1, arg_types.len()) {
-        llshimmedargs.push(get_param(fcx.llfn, fcx.arg_pos(i) as u32));
-    }
-    assert!(!fcx.needs_ret_allocas);
-    let dest = fcx.llretslotptr.get().map(|_|
-        expr::SaveIn(fcx.get_ret_slot(bcx, return_type, "ret_slot"))
-    );
-    bcx = trans_call_inner(bcx,
-                           None,
-                           function_type,
-                           |bcx, _| {
-                               Callee {
-                                   bcx: bcx,
-                                   data: Fn(llshimmedfn),
-                               }
-                           },
-                           ArgVals(llshimmedargs.as_slice()),
-                           dest).bcx;
-
-    bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
-    finish_fn(&fcx, bcx, return_type);
-
-    llfn
-}
-
 /// Translates a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
 ///
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 94ff526debd..9a2bc38acdf 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -550,68 +550,12 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 emit_vtable_methods(bcx, id, substs).into_iter()
             }
             traits::VtableUnboxedClosure(closure_def_id, substs) => {
-                // Look up closure type
-                let self_ty = ty::node_id_to_type(bcx.tcx(), closure_def_id.node);
-                // Apply substitutions from closure param environment.
-                // The substitutions should have no type parameters
-                // remaining after passing through fulfill_obligation
-                let self_ty = self_ty.subst(bcx.tcx(), &substs);
-
-                let mut llfn = trans_fn_ref_with_substs(
+                let llfn = trans_fn_ref_with_substs(
                     bcx,
                     closure_def_id,
                     ExprId(0),
                     substs.clone());
 
-                {
-                    let unboxed_closures = bcx.tcx()
-                                              .unboxed_closures
-                                              .borrow();
-                    let closure_info =
-                        unboxed_closures.get(&closure_def_id)
-                                        .expect("get_vtable(): didn't find \
-                                                 unboxed closure");
-                    if closure_info.kind == ty::FnOnceUnboxedClosureKind {
-                        // Untuple the arguments and create an unboxing shim.
-                        let (new_inputs, new_output) = match self_ty.sty {
-                            ty::ty_unboxed_closure(_, _, ref substs) => {
-                                let mut new_inputs = vec![self_ty.clone()];
-                                match closure_info.closure_type.sig.inputs[0].sty {
-                                    ty::ty_tup(ref elements) => {
-                                        for element in elements.iter() {
-                                            new_inputs.push(element.subst(bcx.tcx(), substs));
-                                        }
-                                    }
-                                    _ => {
-                                        bcx.tcx().sess.bug("get_vtable(): closure \
-                                                            type wasn't a tuple")
-                                    }
-                                }
-                                (new_inputs,
-                                 closure_info.closure_type.sig.output.subst(bcx.tcx(), substs))
-                            },
-                            _ => bcx.tcx().sess.bug("get_vtable(): def wasn't an unboxed closure")
-                        };
-
-                        let closure_type = ty::BareFnTy {
-                            fn_style: closure_info.closure_type.fn_style,
-                            abi: Rust,
-                            sig: ty::FnSig {
-                                inputs: new_inputs,
-                                output: new_output,
-                                variadic: false,
-                            },
-                        };
-                        debug!("get_vtable(): closure type is {}",
-                               closure_type.repr(bcx.tcx()));
-                        llfn = trans_unboxing_shim(bcx,
-                                                   llfn,
-                                                   &closure_type,
-                                                   closure_def_id,
-                                                   &substs);
-                    }
-                }
-
                 (vec!(llfn)).into_iter()
             }
             traits::VtableFnPointer(bare_fn_ty) => {
@@ -701,18 +645,15 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            token::get_name(name));
                     Some(C_null(Type::nil(ccx).ptr_to())).into_iter()
                 } else {
-                    let mut fn_ref = trans_fn_ref_with_substs(
+                    let fn_ref = trans_fn_ref_with_substs(
                         bcx,
                         m_id,
                         ExprId(0),
                         substs.clone());
-                    if m.explicit_self == ty::ByValueExplicitSelfCategory {
-                        fn_ref = trans_unboxing_shim(bcx,
-                                                     fn_ref,
-                                                     &m.fty,
-                                                     m_id,
-                                                     &substs);
-                    }
+
+                    // currently, at least, by-value self is not object safe
+                    assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
+
                     Some(fn_ref).into_iter()
                 }
             }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index adcfc491dcc..d3879e49034 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -315,23 +315,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                 get_method_index(tcx, &*new_trait_ref,
                                  trait_ref.clone(), method_num);
 
-            // FIXME Hacky. By-value `self` methods in objects ought to be
-            // just a special case of passing ownership of a DST value
-            // as a parameter. *But* we currently hack them in and tie them to
-            // the particulars of the `Box` type. So basically for a `fn foo(self,...)`
-            // method invoked on an object, we don't want the receiver type to be
-            // `TheTrait`, but rather `Box<TheTrait>`. Yuck.
-            let mut m = m;
-            match m.explicit_self {
-                ty::ByValueExplicitSelfCategory => {
-                    let mut n = (*m).clone();
-                    let self_ty = n.fty.sig.inputs[0];
-                    n.fty.sig.inputs[0] = ty::mk_uniq(tcx, self_ty);
-                    m = Rc::new(n);
-                }
-                _ => { }
-            }
-
             let xform_self_ty =
                 this.xform_self_ty(&m, &new_trait_ref.substs);
 
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index 7c5ceb6f510..415a3d53fb2 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -149,14 +149,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  object_trait: &ty::TraitRef<'tcx>,
                                  span: Span) {
-    // Skip the fn_once lang item trait since only the compiler should call
-    // `call_once` which is the method which takes self by value. What could go
-    // wrong?
-    match tcx.lang_items.fn_once_trait() {
-        Some(def_id) if def_id == object_trait.def_id => return,
-        _ => {}
-    }
-
     let trait_items = ty::trait_items(tcx, object_trait.def_id);
 
     let mut errors = Vec::new();
diff --git a/src/test/run-pass/issue-16739.rs b/src/test/run-pass/issue-16739.rs
index 6dcdc1d1086..552ce565f6b 100644
--- a/src/test/run-pass/issue-16739.rs
+++ b/src/test/run-pass/issue-16739.rs
@@ -11,29 +11,29 @@
 #![feature(unboxed_closures)]
 
 // Test that unboxing shim for calling rust-call ABI methods through a
-// trait box works and does not cause an ICE
+// trait box works and does not cause an ICE.
 
 struct Foo { foo: uint }
 
-impl FnOnce<(), uint> for Foo {
-    extern "rust-call" fn call_once(self, _: ()) -> uint { self.foo }
+impl FnMut<(), uint> for Foo {
+    extern "rust-call" fn call_mut(&mut self, _: ()) -> uint { self.foo }
 }
 
-impl FnOnce<(uint,), uint> for Foo {
-    extern "rust-call" fn call_once(self, (x,): (uint,)) -> uint { self.foo + x }
+impl FnMut<(uint,), uint> for Foo {
+    extern "rust-call" fn call_mut(&mut self, (x,): (uint,)) -> uint { self.foo + x }
 }
 
-impl FnOnce<(uint, uint), uint> for Foo {
-    extern "rust-call" fn call_once(self, (x, y): (uint, uint)) -> uint { self.foo + x + y }
+impl FnMut<(uint, uint), uint> for Foo {
+    extern "rust-call" fn call_mut(&mut self, (x, y): (uint, uint)) -> uint { self.foo + x + y }
 }
 
 fn main() {
-    let f = box Foo { foo: 42 } as Box<FnOnce<(), uint>>;
-    assert_eq!(f.call_once(()), 42);
+    let mut f = box Foo { foo: 42 } as Box<FnMut<(), uint>>;
+    assert_eq!(f.call_mut(()), 42);
 
-    let f = box Foo { foo: 40 } as Box<FnOnce<(uint,), uint>>;
-    assert_eq!(f.call_once((2,)), 42);
+    let mut f = box Foo { foo: 40 } as Box<FnMut<(uint,), uint>>;
+    assert_eq!(f.call_mut((2,)), 42);
 
-    let f = box Foo { foo: 40 } as Box<FnOnce<(uint, uint), uint>>;
-    assert_eq!(f.call_once((1, 1)), 42);
+    let mut f = box Foo { foo: 40 } as Box<FnMut<(uint, uint), uint>>;
+    assert_eq!(f.call_mut((1, 1)), 42);
 }
diff --git a/src/test/run-pass/issue-18883.rs b/src/test/run-pass/issue-18883.rs
deleted file mode 100644
index c54844f570b..00000000000
--- a/src/test/run-pass/issue-18883.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that we don't ICE due to encountering unsubstituted type
-// parameters when untupling FnOnce parameters during translation of
-// an unboxing shim.
-
-#![feature(unboxed_closures)]
-
-fn main() {
-    let _: Box<FnOnce<(),()>> = box move |&mut:| {};
-}
diff --git a/src/test/run-pass/unboxed-closures-monomorphization.rs b/src/test/run-pass/unboxed-closures-monomorphization.rs
index cd97fd96fa3..dfc234e87cd 100644
--- a/src/test/run-pass/unboxed-closures-monomorphization.rs
+++ b/src/test/run-pass/unboxed-closures-monomorphization.rs
@@ -14,26 +14,26 @@
 #![feature(unboxed_closures)]
 
 fn main(){
-    fn bar<'a, T:'a> (t: T) -> Box<FnOnce<(),T> + 'a> {
-        box move |:| t
+    fn bar<'a, T:Clone+'a> (t: T) -> Box<FnMut<(),T> + 'a> {
+        box move |&mut:| t.clone()
     }
 
-    let f = bar(42u);
-    assert_eq!(f.call_once(()), 42);
+    let mut f = bar(42u);
+    assert_eq!(f.call_mut(()), 42);
 
-    let f = bar("forty-two");
-    assert_eq!(f.call_once(()), "forty-two");
+    let mut f = bar("forty-two");
+    assert_eq!(f.call_mut(()), "forty-two");
 
     let x = 42u;
-    let f = bar(&x);
-    assert_eq!(f.call_once(()), &x);
+    let mut f = bar(&x);
+    assert_eq!(f.call_mut(()), &x);
 
-    #[deriving(Show, PartialEq)]
+    #[deriving(Clone, Show, PartialEq)]
     struct Foo(uint, &'static str);
 
     impl Copy for Foo {}
 
     let x = Foo(42, "forty-two");
-    let f = bar(x);
-    assert_eq!(f.call_once(()), x);
+    let mut f = bar(x);
+    assert_eq!(f.call_mut(()), x);
 }
diff --git a/src/test/run-pass/unboxed-closures-prelude.rs b/src/test/run-pass/unboxed-closures-prelude.rs
index 6f672f2f282..e31ef169e16 100644
--- a/src/test/run-pass/unboxed-closures-prelude.rs
+++ b/src/test/run-pass/unboxed-closures-prelude.rs
@@ -13,7 +13,16 @@
 #![feature(unboxed_closures)]
 
 fn main() {
-    let task: Box<FnOnce(int) -> int> = box |: x| x;
-    task.call_once((0i, ));
+    let task: Box<Fn(int) -> int> = box |&: x| x;
+    task.call((0i, ));
+
+    let mut task: Box<FnMut(int) -> int> = box |&mut: x| x;
+    task.call_mut((0i, ));
+
+    call(|:x| x, 22);
+}
+
+fn call<F:FnOnce(int) -> int>(f: F, x: int) -> int {
+    f.call_once((x,))
 }
 
diff --git a/src/test/run-pass/unboxed-closures-unboxing-shim.rs b/src/test/run-pass/unboxed-closures-unboxing-shim.rs
deleted file mode 100644
index c41aeaa673f..00000000000
--- a/src/test/run-pass/unboxed-closures-unboxing-shim.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(unboxed_closures)]
-
-use std::ops::FnOnce;
-
-fn main() {
-    let task: Box<FnOnce(int) -> int> = box |: x| x;
-    assert!(task.call_once((1234i,)) == 1234i);
-}
-