Rollup merge of #22301 - nikomatsakis:object-safe-sized-methods, r=huonw
RFC 817 is not yet accepted, but I wanted to put this code up so people can see how it works. And to be ready lest it should be accepted. cc rust-lang/rfcs#817
This commit is contained in:
commit
5676f6084b
14 changed files with 252 additions and 66 deletions
|
|
@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
|
|||
|
||||
fn main() {
|
||||
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
|
||||
//~^ ERROR object-safe
|
||||
//~| ERROR mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `()`
|
||||
//~| found `Box<core::ops::FnOnce(isize)>`
|
||||
//~| expected ()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@ impl Foo for Thing {
|
|||
fn foo<T>(&self, _: &T) {}
|
||||
}
|
||||
|
||||
#[inline(never)] fn foo(b: &Bar) { b.foo(&0_usize) }
|
||||
#[inline(never)]
|
||||
fn foo(b: &Bar) {
|
||||
b.foo(&0usize)
|
||||
//~^ ERROR the trait `Foo` is not implemented for the type `Bar`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut thing = Thing;
|
||||
|
|
|
|||
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal file
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// 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.
|
||||
|
||||
// Check that while a trait with by-value self is object-safe, we
|
||||
// can't actually invoke it from an object (yet...?).
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
trait Bar {
|
||||
fn bar(self);
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
fn baz(self: Self);
|
||||
}
|
||||
|
||||
fn use_bar(t: Box<Bar>) {
|
||||
t.bar() //~ ERROR cannot move a value of type Bar
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
||||
|
|
@ -8,8 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits with a `fn(self)` method.
|
||||
// Check that a trait with by-value self is considered object-safe.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Bar {
|
||||
fn bar(self);
|
||||
|
|
@ -19,29 +21,35 @@ trait Baz {
|
|||
fn baz(self: Self);
|
||||
}
|
||||
|
||||
trait Quux {
|
||||
// Legal because of the where clause:
|
||||
fn baz(self: Self) where Self : Sized;
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR `Bar` is not object-safe
|
||||
//~| NOTE method `bar` has a receiver type of `Self`
|
||||
t // legal
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
t as &Bar
|
||||
//~^ ERROR `Bar` is not object-safe
|
||||
//~| NOTE method `bar` has a receiver type of `Self`
|
||||
t as &Bar // legal
|
||||
}
|
||||
|
||||
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
||||
t
|
||||
//~^ ERROR `Baz` is not object-safe
|
||||
//~| NOTE method `baz` has a receiver type of `Self`
|
||||
t // legal
|
||||
}
|
||||
|
||||
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
|
||||
t as &Baz
|
||||
//~^ ERROR `Baz` is not object-safe
|
||||
//~| NOTE method `baz` has a receiver type of `Self`
|
||||
t as &Baz // legal
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||
t
|
||||
}
|
||||
|
||||
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
|
||||
t as &Quux
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { //~ ERROR compilation successful
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,18 @@
|
|||
// except according to those terms.
|
||||
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits with generic methods.
|
||||
// from traits with generic methods, unless `where Self : Sized` is
|
||||
// present.
|
||||
|
||||
trait Bar {
|
||||
fn bar<T>(&self, t: T);
|
||||
}
|
||||
|
||||
trait Quux {
|
||||
fn bar<T>(&self, t: T)
|
||||
where Self : Sized;
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR `Bar` is not object-safe
|
||||
|
|
@ -27,5 +33,13 @@ fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
|||
//~| NOTE method `bar` has generic type parameters
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||
t
|
||||
}
|
||||
|
||||
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
|
||||
t as &Quux
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
// except according to those terms.
|
||||
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// form traits that make use of `Self` in an argument or return position.
|
||||
// form traits that make use of `Self` in an argument or return
|
||||
// position, unless `where Self : Sized` is present..
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self, x: &Self);
|
||||
|
|
@ -19,6 +20,10 @@ trait Baz {
|
|||
fn bar(&self) -> Self;
|
||||
}
|
||||
|
||||
trait Quux {
|
||||
fn get(&self, s: &Self) -> Self where Self : Sized;
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
t
|
||||
//~^ ERROR `Bar` is not object-safe
|
||||
|
|
@ -43,5 +48,13 @@ fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
|
|||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &Quux {
|
||||
t
|
||||
}
|
||||
|
||||
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
|
||||
t as &Quux
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ fn main() {
|
|||
10.dup::<i32>(); //~ ERROR does not take type parameters
|
||||
10.blah::<i32, i32>(); //~ ERROR incorrect number of type parameters
|
||||
(box 10 as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
|
||||
//~^ ERROR the trait `bar` is not implemented for the type `bar`
|
||||
}
|
||||
|
|
|
|||
46
src/test/run-pass/object-safety-sized-self-by-value-self.rs
Normal file
46
src/test/run-pass/object-safety-sized-self-by-value-self.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
// Check that a trait is still object-safe (and usable) if it has
|
||||
// methods with by-value self so long as they require `Self : Sized`.
|
||||
|
||||
trait Counter {
|
||||
fn tick(&mut self) -> u32;
|
||||
fn get(self) -> u32 where Self : Sized;
|
||||
}
|
||||
|
||||
struct CCounter {
|
||||
c: u32
|
||||
}
|
||||
|
||||
impl Counter for CCounter {
|
||||
fn tick(&mut self) -> u32 { self.c += 1; self.c }
|
||||
fn get(self) -> u32 where Self : Sized { self.c }
|
||||
}
|
||||
|
||||
fn tick1<C:Counter>(mut c: C) -> u32 {
|
||||
tick2(&mut c);
|
||||
c.get()
|
||||
}
|
||||
|
||||
fn tick2(c: &mut Counter) {
|
||||
tick3(c);
|
||||
}
|
||||
|
||||
fn tick3<C:?Sized+Counter>(c: &mut C) {
|
||||
c.tick();
|
||||
c.tick();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut c = CCounter { c: 0 };
|
||||
let value = tick1(c);
|
||||
assert_eq!(value, 2);
|
||||
}
|
||||
46
src/test/run-pass/object-safety-sized-self-generic-method.rs
Normal file
46
src/test/run-pass/object-safety-sized-self-generic-method.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
// Check that a trait is still object-safe (and usable) if it has
|
||||
// generic methods so long as they require `Self : Sized`.
|
||||
|
||||
trait Counter {
|
||||
fn tick(&mut self) -> u32;
|
||||
fn with<F:FnOnce(u32)>(&self, f: F) where Self : Sized;
|
||||
}
|
||||
|
||||
struct CCounter {
|
||||
c: u32
|
||||
}
|
||||
|
||||
impl Counter for CCounter {
|
||||
fn tick(&mut self) -> u32 { self.c += 1; self.c }
|
||||
fn with<F:FnOnce(u32)>(&self, f: F) { f(self.c); }
|
||||
}
|
||||
|
||||
fn tick1<C:Counter>(c: &mut C) {
|
||||
tick2(c);
|
||||
c.with(|i| ());
|
||||
}
|
||||
|
||||
fn tick2(c: &mut Counter) {
|
||||
tick3(c);
|
||||
}
|
||||
|
||||
fn tick3<C:?Sized+Counter>(c: &mut C) {
|
||||
c.tick();
|
||||
c.tick();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut c = CCounter { c: 0 };
|
||||
tick1(&mut c);
|
||||
assert_eq!(c.tick(), 3);
|
||||
}
|
||||
47
src/test/run-pass/object-safety-sized-self-return-Self.rs
Normal file
47
src/test/run-pass/object-safety-sized-self-return-Self.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// 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.
|
||||
|
||||
// Check that a trait is still object-safe (and usable) if it has
|
||||
// methods that return `Self` so long as they require `Self : Sized`.
|
||||
|
||||
trait Counter {
|
||||
fn new() -> Self where Self : Sized;
|
||||
fn tick(&mut self) -> u32;
|
||||
}
|
||||
|
||||
struct CCounter {
|
||||
c: u32
|
||||
}
|
||||
|
||||
impl Counter for CCounter {
|
||||
fn new() -> CCounter { CCounter { c: 0 } }
|
||||
fn tick(&mut self) -> u32 { self.c += 1; self.c }
|
||||
}
|
||||
|
||||
fn preticked<C:Counter>() -> C {
|
||||
let mut c: C = Counter::new();
|
||||
tick(&mut c);
|
||||
c
|
||||
}
|
||||
|
||||
fn tick(c: &mut Counter) {
|
||||
tick_generic(c);
|
||||
}
|
||||
|
||||
fn tick_generic<C:?Sized+Counter>(c: &mut C) {
|
||||
c.tick();
|
||||
c.tick();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut c = preticked::<CCounter>();
|
||||
tick(&mut c);
|
||||
assert_eq!(c.tick(), 5);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue