Skip to content

Commit

Permalink
Fallout from changing fn traits to use inheritance rather than bridge
Browse files Browse the repository at this point in the history
impls. This is a [breaking-change] (for gated code) in that when you
implement `Fn` (`FnMut`) you must also implement `FnOnce`. This commit
demonstrates how to fix it.
  • Loading branch information
nikomatsakis committed Mar 23, 2015
1 parent 3760113 commit 9330bae
Show file tree
Hide file tree
Showing 28 changed files with 216 additions and 59 deletions.
10 changes: 8 additions & 2 deletions src/libcollectionstest/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,21 @@ struct Counter<'a, 'b> {
}

impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
type Output = bool;

extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
true
}
}

impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
type Output = bool;

extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
self.call_mut(args)
}
}

fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
// FIXME Replace Counter with `Box<FnMut(_) -> _>`
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,
Expand Down
18 changes: 14 additions & 4 deletions src/test/compile-fail/borrowck-overloaded-call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,36 @@ struct SFn {
}

impl Fn<(isize,)> for SFn {
type Output = isize;

extern "rust-call" fn call(&self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}

impl FnMut<(isize,)> for SFn {
extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) }
}

impl FnOnce<(isize,)> for SFn {
type Output = isize;
extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) }
}

struct SFnMut {
x: isize,
y: isize,
}

impl FnMut<(isize,)> for SFnMut {
type Output = isize;

extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}

impl FnOnce<(isize,)> for SFnMut {
type Output = isize;
extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
}

struct SFnOnce {
x: String,
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/compile-fail/coerce-unsafe-to-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@

fn main() {
let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
//~^ ERROR: is not implemented for the type
//~^ ERROR E0277
//~| ERROR E0277
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/extern-wrong-value-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ fn main() {
let _x: extern "C" fn() = f; // OK
is_fn(f);
//~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
//~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
//~| ERROR the trait `core::ops::FnOnce<()>` is not implemented for the type `extern "C" fn()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,21 @@
struct Foo;
impl Fn<()> for Foo {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
type Output = ();

extern "rust-call" fn call(&self, args: ()) -> () {}
extern "rust-call" fn call(self, args: ()) -> () {}
}
struct Foo1;
impl Fn() for Foo1 {
impl FnOnce() for Foo1 {
//~^ ERROR associated type bindings are not allowed here

extern "rust-call" fn call(&self, args: ()) -> () {}
extern "rust-call" fn call_once(self, args: ()) -> () {}
}
struct Bar;
impl FnMut<()> for Bar {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
type Output = ();

extern "rust-call" fn call_mut(&self, args: ()) -> () {}
}
struct Baz;
impl FnOnce<()> for Baz {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
type Output = ();

extern "rust-call" fn call_once(&self, args: ()) -> () {}
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/fn-trait-formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ fn main() {

needs_fn(1);
//~^ ERROR `core::ops::Fn<(isize,)>`
//~| ERROR `core::ops::Fn<(isize,)>`
//~| ERROR `core::ops::FnOnce<(isize,)>`
}
8 changes: 6 additions & 2 deletions src/test/compile-fail/fn-variance-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
}

fn main() {
apply(&3, takes_mut); //~ ERROR (values differ in mutability)
apply(&3, takes_imm);
apply(&3, takes_mut);
//~^ ERROR (values differ in mutability)
//~| ERROR (values differ in mutability)

apply(&mut 3, takes_mut);
apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability)
apply(&mut 3, takes_imm);
//~^ ERROR (values differ in mutability)
//~| ERROR (values differ in mutability)
}
7 changes: 3 additions & 4 deletions src/test/compile-fail/issue-15094.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ struct Debuger<T> {
x: T
}

impl<T: fmt::Debug> ops::Fn<(),> for Debuger<T> {
impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
type Output = ();

fn call(&self, _args: ()) {
//~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
fn call_once(self, _args: ()) {
//~^ ERROR `call_once` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
println!("{:?}", self.x);
}
}
Expand Down
12 changes: 11 additions & 1 deletion src/test/compile-fail/issue-20225.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,19 @@
struct Foo;

impl<'a, T> Fn<(&'a T,)> for Foo {
extern "rust-call" fn call(&self, (_,): (T,)) {}
//~^ ERROR: has an incompatible type for trait: expected &-ptr
}

impl<'a, T> FnMut<(&'a T,)> for Foo {
extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
//~^ ERROR: has an incompatible type for trait: expected &-ptr
}

impl<'a, T> FnOnce<(&'a T,)> for Foo {
type Output = ();

extern "rust-call" fn call(&self, (_,): (T,)) {}
extern "rust-call" fn call_once(self, (_,): (T,)) {}
//~^ ERROR: has an incompatible type for trait: expected &-ptr
}

Expand Down
9 changes: 7 additions & 2 deletions src/test/compile-fail/overloaded-calls-bad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ struct S {
}

impl FnMut<(isize,)> for S {
type Output = isize;

extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}

impl FnOnce<(isize,)> for S {
type Output = isize;
extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize {
self.call_mut((z,))
}
}

fn main() {
let mut s = S {
x: 3,
Expand Down
6 changes: 5 additions & 1 deletion src/test/compile-fail/overloaded-calls-nontuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ struct S {
}

impl FnMut<isize> for S {
type Output = isize;
extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
self.x + self.y + z
}
}

impl FnOnce<isize> for S {
type Output = isize;
extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
}

fn main() {
let mut s = S {
x: 1,
Expand Down
9 changes: 6 additions & 3 deletions src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,22 @@ use std::ops::{Fn,FnMut,FnOnce};
struct S;

impl FnMut<(isize,)> for S {
type Output = isize;

extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize {
x * x
}
}

impl FnOnce<(isize,)> for S {
type Output = isize;

extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
}

fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
f.call((x,))
}

fn main() {
let x = call_it(&S, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,19 @@ impl<F,A,R> YCombinator<F,A,R> {
}

impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
type Output = R;

extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R {
(self.func)(self, arg)
//~^ ERROR cannot borrow `*self` as mutable more than once at a time
}
}

impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
type Output = R;
extern "rust-call" fn call_once(mut self, args: (A,)) -> R {
self.call_mut(args)
}
}

fn main() {
let mut counter = 0;
let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 {
Expand Down
8 changes: 6 additions & 2 deletions src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ fn a() {
}

fn b() {
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
let y = call_it_mut(&mut square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn c() {
let z = call_it_once(square, 22); //~ ERROR not implemented
let z = call_it_once(square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn main() { }
8 changes: 6 additions & 2 deletions src/test/compile-fail/unboxed-closures-wrong-abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ fn a() {
}

fn b() {
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
let y = call_it_mut(&mut square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn c() {
let z = call_it_once(square, 22); //~ ERROR not implemented
let z = call_it_once(square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn main() { }
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ fn a() {
}

fn b() {
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
let y = call_it_mut(&mut square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn c() {
let z = call_it_once(square, 22); //~ ERROR not implemented
let z = call_it_once(square, 22);
//~^ ERROR not implemented
//~| ERROR not implemented
}

fn main() { }
15 changes: 14 additions & 1 deletion src/test/run-pass/issue-13655.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,27 @@ use std::ops::Fn;
struct Foo<T>(T);

impl<T: Copy> Fn<()> for Foo<T> {
type Output = T;
extern "rust-call" fn call(&self, _: ()) -> T {
match *self {
Foo(t) => t
}
}
}

impl<T: Copy> FnMut<()> for Foo<T> {
extern "rust-call" fn call_mut(&mut self, _: ()) -> T {
self.call(())
}
}

impl<T: Copy> FnOnce<()> for Foo<T> {
type Output = T;

extern "rust-call" fn call_once(self, _: ()) -> T {
self.call(())
}
}

fn main() {
let t: u8 = 1;
println!("{}", Foo(t)());
Expand Down
10 changes: 9 additions & 1 deletion src/test/run-pass/issue-14958.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@ trait Foo { fn dummy(&self) { }}
struct Bar;

impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar {
type Output = ();
extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
}

impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar {
extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) }
}

impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar {
type Output = ();
extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) }
}

struct Baz;

impl Foo for Baz {}
Expand Down
14 changes: 13 additions & 1 deletion src/test/run-pass/issue-14959.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,21 @@ impl Alloy {
}

impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
}

impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile {
extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) {
self.call((_res,))
}
}

impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile {
type Output = ();

extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) {
self.call((_res,))
}
}

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
Expand Down
Loading

0 comments on commit 9330bae

Please sign in to comment.