Skip to content

Commit 698db04

Browse files
committed
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.
1 parent d613381 commit 698db04

File tree

9 files changed

+42
-303
lines changed

9 files changed

+42
-303
lines changed

src/librustc_trans/trans/callee.rs

Lines changed: 1 addition & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ pub use self::CalleeData::*;
1919
pub use self::CallArgs::*;
2020

2121
use arena::TypedArena;
22-
use back::abi;
23-
use back::link;
22+
use back::{abi,link};
2423
use session;
2524
use llvm::{ValueRef, get_param};
2625
use llvm;
@@ -357,153 +356,6 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
357356
llfn
358357
}
359358

360-
/// Translates the adapter that deconstructs a `Box<Trait>` object into
361-
/// `Trait` so that a by-value self method can be called.
362-
pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
363-
llshimmedfn: ValueRef,
364-
fty: &ty::BareFnTy<'tcx>,
365-
method_id: ast::DefId,
366-
substs: &subst::Substs<'tcx>)
367-
-> ValueRef {
368-
let _icx = push_ctxt("trans_unboxing_shim");
369-
let ccx = bcx.ccx();
370-
let tcx = bcx.tcx();
371-
372-
let fty = fty.subst(tcx, substs);
373-
374-
// Transform the self type to `Box<self_type>`.
375-
let self_type = fty.sig.inputs[0];
376-
let boxed_self_type = ty::mk_uniq(tcx, self_type);
377-
let boxed_function_type = ty::FnSig {
378-
inputs: fty.sig.inputs.iter().enumerate().map(|(i, typ)| {
379-
if i == 0 {
380-
boxed_self_type
381-
} else {
382-
*typ
383-
}
384-
}).collect(),
385-
output: fty.sig.output,
386-
variadic: false,
387-
};
388-
let boxed_function_type = ty::BareFnTy {
389-
fn_style: fty.fn_style,
390-
abi: fty.abi,
391-
sig: boxed_function_type,
392-
};
393-
let boxed_function_type = ty::mk_bare_fn(tcx, boxed_function_type);
394-
let function_type = match fty.abi {
395-
synabi::RustCall => {
396-
// We're passing through to a RustCall ABI function, but
397-
// because the shim will already perform untupling, we
398-
// need to pretend the shimmed function does not use
399-
// RustCall so the untupled arguments can be passed
400-
// through verbatim. This is kind of ugly.
401-
let fake_ty = ty::FnSig {
402-
inputs: type_of::untuple_arguments_if_necessary(ccx,
403-
fty.sig.inputs.as_slice(),
404-
fty.abi),
405-
output: fty.sig.output,
406-
variadic: false,
407-
};
408-
let fake_ty = ty::BareFnTy {
409-
fn_style: fty.fn_style,
410-
abi: synabi::Rust,
411-
sig: fake_ty,
412-
};
413-
ty::mk_bare_fn(tcx, fake_ty)
414-
}
415-
_ => {
416-
ty::mk_bare_fn(tcx, fty)
417-
}
418-
};
419-
420-
let function_name = ty::with_path(tcx, method_id, |path| {
421-
link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
422-
});
423-
let llfn = decl_internal_rust_fn(ccx,
424-
boxed_function_type,
425-
function_name.as_slice());
426-
427-
let block_arena = TypedArena::new();
428-
let empty_param_substs = Substs::trans_empty();
429-
let return_type = ty::ty_fn_ret(boxed_function_type);
430-
let fcx = new_fn_ctxt(ccx,
431-
llfn,
432-
ast::DUMMY_NODE_ID,
433-
false,
434-
return_type,
435-
&empty_param_substs,
436-
None,
437-
&block_arena);
438-
let mut bcx = init_function(&fcx, false, return_type);
439-
440-
// Create the substituted versions of the self type.
441-
let arg_scope = fcx.push_custom_cleanup_scope();
442-
let arg_scope_id = cleanup::CustomScope(arg_scope);
443-
let boxed_self_type = ty::ty_fn_args(boxed_function_type)[0];
444-
let arg_types = ty::ty_fn_args(function_type);
445-
let self_type = arg_types[0];
446-
let boxed_self_kind = arg_kind(&fcx, boxed_self_type);
447-
448-
// Create a datum for self.
449-
let llboxedself = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
450-
let llboxedself = Datum::new(llboxedself,
451-
boxed_self_type,
452-
boxed_self_kind);
453-
let boxed_self =
454-
unpack_datum!(bcx,
455-
llboxedself.to_lvalue_datum_in_scope(bcx,
456-
"boxedself",
457-
arg_scope_id));
458-
459-
// This `Load` is needed because lvalue data are always by-ref.
460-
let llboxedself = Load(bcx, boxed_self.val);
461-
462-
let llself = if type_is_immediate(ccx, self_type) {
463-
let llboxedself = Load(bcx, llboxedself);
464-
immediate_rvalue(llboxedself, self_type)
465-
} else {
466-
let llself = rvalue_scratch_datum(bcx, self_type, "self");
467-
memcpy_ty(bcx, llself.val, llboxedself, self_type);
468-
llself
469-
};
470-
471-
// Make sure we don't free the box twice!
472-
boxed_self.kind.post_store(bcx, boxed_self.val, boxed_self_type);
473-
474-
// Schedule a cleanup to free the box.
475-
fcx.schedule_free_value(arg_scope_id,
476-
llboxedself,
477-
cleanup::HeapExchange,
478-
self_type);
479-
480-
// Now call the function.
481-
let mut llshimmedargs = vec!(llself.val);
482-
for i in range(1, arg_types.len()) {
483-
llshimmedargs.push(get_param(fcx.llfn, fcx.arg_pos(i) as u32));
484-
}
485-
assert!(!fcx.needs_ret_allocas);
486-
let dest = fcx.llretslotptr.get().map(|_|
487-
expr::SaveIn(fcx.get_ret_slot(bcx, return_type, "ret_slot"))
488-
);
489-
bcx = trans_call_inner(bcx,
490-
None,
491-
function_type,
492-
|bcx, _| {
493-
Callee {
494-
bcx: bcx,
495-
data: Fn(llshimmedfn),
496-
}
497-
},
498-
ArgVals(llshimmedargs.as_slice()),
499-
dest).bcx;
500-
501-
bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
502-
finish_fn(&fcx, bcx, return_type);
503-
504-
llfn
505-
}
506-
507359
/// Translates a reference to a fn/method item, monomorphizing and
508360
/// inlining as it goes.
509361
///

src/librustc_trans/trans/meth.rs

Lines changed: 6 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -550,68 +550,12 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
550550
emit_vtable_methods(bcx, id, substs).into_iter()
551551
}
552552
traits::VtableUnboxedClosure(closure_def_id, substs) => {
553-
// Look up closure type
554-
let self_ty = ty::node_id_to_type(bcx.tcx(), closure_def_id.node);
555-
// Apply substitutions from closure param environment.
556-
// The substitutions should have no type parameters
557-
// remaining after passing through fulfill_obligation
558-
let self_ty = self_ty.subst(bcx.tcx(), &substs);
559-
560-
let mut llfn = trans_fn_ref_with_substs(
553+
let llfn = trans_fn_ref_with_substs(
561554
bcx,
562555
closure_def_id,
563556
ExprId(0),
564557
substs.clone());
565558

566-
{
567-
let unboxed_closures = bcx.tcx()
568-
.unboxed_closures
569-
.borrow();
570-
let closure_info =
571-
unboxed_closures.get(&closure_def_id)
572-
.expect("get_vtable(): didn't find \
573-
unboxed closure");
574-
if closure_info.kind == ty::FnOnceUnboxedClosureKind {
575-
// Untuple the arguments and create an unboxing shim.
576-
let (new_inputs, new_output) = match self_ty.sty {
577-
ty::ty_unboxed_closure(_, _, ref substs) => {
578-
let mut new_inputs = vec![self_ty.clone()];
579-
match closure_info.closure_type.sig.inputs[0].sty {
580-
ty::ty_tup(ref elements) => {
581-
for element in elements.iter() {
582-
new_inputs.push(element.subst(bcx.tcx(), substs));
583-
}
584-
}
585-
_ => {
586-
bcx.tcx().sess.bug("get_vtable(): closure \
587-
type wasn't a tuple")
588-
}
589-
}
590-
(new_inputs,
591-
closure_info.closure_type.sig.output.subst(bcx.tcx(), substs))
592-
},
593-
_ => bcx.tcx().sess.bug("get_vtable(): def wasn't an unboxed closure")
594-
};
595-
596-
let closure_type = ty::BareFnTy {
597-
fn_style: closure_info.closure_type.fn_style,
598-
abi: Rust,
599-
sig: ty::FnSig {
600-
inputs: new_inputs,
601-
output: new_output,
602-
variadic: false,
603-
},
604-
};
605-
debug!("get_vtable(): closure type is {}",
606-
closure_type.repr(bcx.tcx()));
607-
llfn = trans_unboxing_shim(bcx,
608-
llfn,
609-
&closure_type,
610-
closure_def_id,
611-
&substs);
612-
}
613-
}
614-
615559
(vec!(llfn)).into_iter()
616560
}
617561
traits::VtableFnPointer(bare_fn_ty) => {
@@ -701,18 +645,15 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
701645
token::get_name(name));
702646
Some(C_null(Type::nil(ccx).ptr_to())).into_iter()
703647
} else {
704-
let mut fn_ref = trans_fn_ref_with_substs(
648+
let fn_ref = trans_fn_ref_with_substs(
705649
bcx,
706650
m_id,
707651
ExprId(0),
708652
substs.clone());
709-
if m.explicit_self == ty::ByValueExplicitSelfCategory {
710-
fn_ref = trans_unboxing_shim(bcx,
711-
fn_ref,
712-
&m.fty,
713-
m_id,
714-
&substs);
715-
}
653+
654+
// currently, at least, by-value self is not object safe
655+
assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
656+
716657
Some(fn_ref).into_iter()
717658
}
718659
}

src/librustc_typeck/check/method/probe.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -315,23 +315,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
315315
get_method_index(tcx, &*new_trait_ref,
316316
trait_ref.clone(), method_num);
317317

318-
// FIXME Hacky. By-value `self` methods in objects ought to be
319-
// just a special case of passing ownership of a DST value
320-
// as a parameter. *But* we currently hack them in and tie them to
321-
// the particulars of the `Box` type. So basically for a `fn foo(self,...)`
322-
// method invoked on an object, we don't want the receiver type to be
323-
// `TheTrait`, but rather `Box<TheTrait>`. Yuck.
324-
let mut m = m;
325-
match m.explicit_self {
326-
ty::ByValueExplicitSelfCategory => {
327-
let mut n = (*m).clone();
328-
let self_ty = n.fty.sig.inputs[0];
329-
n.fty.sig.inputs[0] = ty::mk_uniq(tcx, self_ty);
330-
m = Rc::new(n);
331-
}
332-
_ => { }
333-
}
334-
335318
let xform_self_ty =
336319
this.xform_self_ty(&m, &new_trait_ref.substs);
337320

src/librustc_typeck/check/vtable.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
149149
fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
150150
object_trait: &ty::TraitRef<'tcx>,
151151
span: Span) {
152-
// Skip the fn_once lang item trait since only the compiler should call
153-
// `call_once` which is the method which takes self by value. What could go
154-
// wrong?
155-
match tcx.lang_items.fn_once_trait() {
156-
Some(def_id) if def_id == object_trait.def_id => return,
157-
_ => {}
158-
}
159-
160152
let trait_items = ty::trait_items(tcx, object_trait.def_id);
161153

162154
let mut errors = Vec::new();

src/test/run-pass/issue-16739.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@
1111
#![feature(unboxed_closures)]
1212

1313
// Test that unboxing shim for calling rust-call ABI methods through a
14-
// trait box works and does not cause an ICE
14+
// trait box works and does not cause an ICE.
1515

1616
struct Foo { foo: uint }
1717

18-
impl FnOnce<(), uint> for Foo {
19-
extern "rust-call" fn call_once(self, _: ()) -> uint { self.foo }
18+
impl FnMut<(), uint> for Foo {
19+
extern "rust-call" fn call_mut(&mut self, _: ()) -> uint { self.foo }
2020
}
2121

22-
impl FnOnce<(uint,), uint> for Foo {
23-
extern "rust-call" fn call_once(self, (x,): (uint,)) -> uint { self.foo + x }
22+
impl FnMut<(uint,), uint> for Foo {
23+
extern "rust-call" fn call_mut(&mut self, (x,): (uint,)) -> uint { self.foo + x }
2424
}
2525

26-
impl FnOnce<(uint, uint), uint> for Foo {
27-
extern "rust-call" fn call_once(self, (x, y): (uint, uint)) -> uint { self.foo + x + y }
26+
impl FnMut<(uint, uint), uint> for Foo {
27+
extern "rust-call" fn call_mut(&mut self, (x, y): (uint, uint)) -> uint { self.foo + x + y }
2828
}
2929

3030
fn main() {
31-
let f = box Foo { foo: 42 } as Box<FnOnce<(), uint>>;
32-
assert_eq!(f.call_once(()), 42);
31+
let mut f = box Foo { foo: 42 } as Box<FnMut<(), uint>>;
32+
assert_eq!(f.call_mut(()), 42);
3333

34-
let f = box Foo { foo: 40 } as Box<FnOnce<(uint,), uint>>;
35-
assert_eq!(f.call_once((2,)), 42);
34+
let mut f = box Foo { foo: 40 } as Box<FnMut<(uint,), uint>>;
35+
assert_eq!(f.call_mut((2,)), 42);
3636

37-
let f = box Foo { foo: 40 } as Box<FnOnce<(uint, uint), uint>>;
38-
assert_eq!(f.call_once((1, 1)), 42);
37+
let mut f = box Foo { foo: 40 } as Box<FnMut<(uint, uint), uint>>;
38+
assert_eq!(f.call_mut((1, 1)), 42);
3939
}

src/test/run-pass/issue-18883.rs

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/test/run-pass/unboxed-closures-monomorphization.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,26 @@
1414
#![feature(unboxed_closures)]
1515

1616
fn main(){
17-
fn bar<'a, T:'a> (t: T) -> Box<FnOnce<(),T> + 'a> {
18-
box move |:| t
17+
fn bar<'a, T:Clone+'a> (t: T) -> Box<FnMut<(),T> + 'a> {
18+
box move |&mut:| t.clone()
1919
}
2020

21-
let f = bar(42u);
22-
assert_eq!(f.call_once(()), 42);
21+
let mut f = bar(42u);
22+
assert_eq!(f.call_mut(()), 42);
2323

24-
let f = bar("forty-two");
25-
assert_eq!(f.call_once(()), "forty-two");
24+
let mut f = bar("forty-two");
25+
assert_eq!(f.call_mut(()), "forty-two");
2626

2727
let x = 42u;
28-
let f = bar(&x);
29-
assert_eq!(f.call_once(()), &x);
28+
let mut f = bar(&x);
29+
assert_eq!(f.call_mut(()), &x);
3030

31-
#[deriving(Show, PartialEq)]
31+
#[deriving(Clone, Show, PartialEq)]
3232
struct Foo(uint, &'static str);
3333

3434
impl Copy for Foo {}
3535

3636
let x = Foo(42, "forty-two");
37-
let f = bar(x);
38-
assert_eq!(f.call_once(()), x);
37+
let mut f = bar(x);
38+
assert_eq!(f.call_mut(()), x);
3939
}

0 commit comments

Comments
 (0)