Auto merge of #54183 - qnighy:by-value-object-safety, r=oli-obk
Implement by-value object safety This PR implements **by-value object safety**, which is part of unsized rvalues #48055. That means, with `#![feature(unsized_locals)]`, you can call a method `fn foo(self, ...)` on trait objects. One aim of this is to enable `Box<FnOnce>` in the near future. The difficulty here is this: when constructing a vtable for a trait `Foo`, we can't just put the function `<T as Foo>::foo` into the table. If `T` is no larger than `usize`, `self` is usually passed directly. However, as the caller of the vtable doesn't know the concrete `Self` type, we want a variant of `<T as Foo>::foo` where `self` is always passed by reference. Therefore, when the compiler encounters such a method to be generated as a vtable entry, it produces a newly introduced instance called `InstanceDef::VtableShim(def_id)` (that wraps the original instance). the shim just derefs the receiver and calls the original method. We give different symbol names for the shims by appending `::{{vtable-shim}}` to the symbol path (and also adding vtable-shimness as an ingredient to the symbol hash). r? @eddyb
This commit is contained in:
commit
cae6efc37d
46 changed files with 870 additions and 171 deletions
|
|
@ -0,0 +1,55 @@
|
|||
#![feature(unsized_locals)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl FnOnce<()> for A {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (): ()) -> Self::Output {
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
struct B(i32);
|
||||
|
||||
impl FnOnce<()> for B {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (): ()) -> Self::Output {
|
||||
format!("{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct C(String);
|
||||
|
||||
impl FnOnce<()> for C {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (): ()) -> Self::Output {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct D(Box<String>);
|
||||
|
||||
impl FnOnce<()> for D {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (): ()) -> Self::Output {
|
||||
*self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(A) as Box<dyn FnOnce<(), Output = String>>);
|
||||
assert_eq!(x.call_once(()), format!("hello"));
|
||||
let x = *(Box::new(B(42)) as Box<dyn FnOnce<(), Output = String>>);
|
||||
assert_eq!(x.call_once(()), format!("42"));
|
||||
let x = *(Box::new(C(format!("jumping fox"))) as Box<dyn FnOnce<(), Output = String>>);
|
||||
assert_eq!(x.call_once(()), format!("jumping fox"));
|
||||
let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box<dyn FnOnce<(), Output = String>>);
|
||||
assert_eq!(x.call_once(()), format!("lazy dog"));
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#![feature(unsized_locals)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
pub trait FnOnce<Args> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl FnOnce<(String, Box<str>)> for A {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output {
|
||||
assert_eq!(&s1 as &str, "s1");
|
||||
assert_eq!(&s2 as &str, "s2");
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
struct B(i32);
|
||||
|
||||
impl FnOnce<(String, Box<str>)> for B {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output {
|
||||
assert_eq!(&s1 as &str, "s1");
|
||||
assert_eq!(&s2 as &str, "s2");
|
||||
format!("{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct C(String);
|
||||
|
||||
impl FnOnce<(String, Box<str>)> for C {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output {
|
||||
assert_eq!(&s1 as &str, "s1");
|
||||
assert_eq!(&s2 as &str, "s2");
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct D(Box<String>);
|
||||
|
||||
impl FnOnce<(String, Box<str>)> for D {
|
||||
type Output = String;
|
||||
extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output {
|
||||
assert_eq!(&s1 as &str, "s1");
|
||||
assert_eq!(&s2 as &str, "s2");
|
||||
*self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
|
||||
let x = *(Box::new(A) as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
|
||||
assert_eq!(x.call_once((s1, s2)), format!("hello"));
|
||||
let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
|
||||
let x = *(Box::new(B(42)) as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
|
||||
assert_eq!(x.call_once((s1, s2)), format!("42"));
|
||||
let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
|
||||
let x = *(Box::new(C(format!("jumping fox")))
|
||||
as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
|
||||
assert_eq!(x.call_once((s1, s2)), format!("jumping fox"));
|
||||
let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
|
||||
let x = *(Box::new(D(Box::new(format!("lazy dog"))))
|
||||
as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
|
||||
assert_eq!(x.call_once((s1, s2)), format!("lazy dog"));
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl Foo for A {
|
||||
fn foo(self) -> String {
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
struct B(i32);
|
||||
|
||||
impl Foo for B {
|
||||
fn foo(self) -> String {
|
||||
format!("{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct C(String);
|
||||
|
||||
impl Foo for C {
|
||||
fn foo(self) -> String {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
struct D(Box<String>);
|
||||
|
||||
impl Foo for D {
|
||||
fn foo(self) -> String {
|
||||
*self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(A) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("hello"));
|
||||
let x = *(Box::new(B(42)) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("42"));
|
||||
let x = *(Box::new(C(format!("jumping fox"))) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("jumping fox"));
|
||||
let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("lazy dog"));
|
||||
}
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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(unsized_locals)]
|
||||
|
||||
use std::fmt;
|
||||
|
|
|
|||
47
src/test/run-pass/unsized-locals/autoderef.rs
Normal file
47
src/test/run-pass/unsized-locals/autoderef.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String;
|
||||
}
|
||||
|
||||
impl Foo for [char] {
|
||||
fn foo(self) -> String {
|
||||
self.iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo for str {
|
||||
fn foo(self) -> String {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo for dyn FnMut() -> String {
|
||||
fn foo(mut self) -> String {
|
||||
self()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>);
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>;
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = *("hello".to_owned().into_boxed_str());
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = *(Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>);
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
|
||||
let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
|
||||
assert_eq!(&x.foo() as &str, "hello");
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String {
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl Foo for A {}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(A) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("hello"));
|
||||
|
||||
// I'm not sure whether we want this to work
|
||||
let x = Box::new(A) as Box<dyn Foo>;
|
||||
assert_eq!(x.foo(), format!("hello"));
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl Foo for A {
|
||||
fn foo(self) -> String {
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(A) as Box<dyn Foo>);
|
||||
assert_eq!(x.foo(), format!("hello"));
|
||||
|
||||
// I'm not sure whether we want this to work
|
||||
let x = Box::new(A) as Box<dyn Foo>;
|
||||
assert_eq!(x.foo(), format!("hello"));
|
||||
}
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(unsized_locals)]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(unsized_locals)]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion, unsized_locals)]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(unsized_locals)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: symbol-name(_ZN5basic4main17h2138d548fb9814b6E)
|
||||
error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E)
|
||||
--> $DIR/basic.rs:13:1
|
||||
|
|
||||
LL | #[rustc_symbol_name] //~ ERROR _ZN5basic4main
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: symbol-name(_ZN5impl13foo3Foo3bar17h8da62e6147ff602fE)
|
||||
error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E)
|
||||
--> $DIR/impl1.rs:18:9
|
||||
|
|
||||
LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar
|
||||
|
|
@ -10,7 +10,7 @@ error: item-path(foo::Foo::bar)
|
|||
LL | #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar)
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h374cb8f6185db9b4E)
|
||||
error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E)
|
||||
--> $DIR/impl1.rs:28:9
|
||||
|
|
||||
LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
|
||||
|
|
|
|||
51
src/test/ui/unsized-locals/borrow-after-move.nll.stderr
Normal file
51
src/test/ui/unsized-locals/borrow-after-move.nll.stderr
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:20:24
|
||||
|
|
||||
LL | let y = *x;
|
||||
| -- value moved here
|
||||
LL | drop_unsized(y);
|
||||
LL | println!("{}", &x);
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `y`
|
||||
--> $DIR/borrow-after-move.rs:22:24
|
||||
|
|
||||
LL | drop_unsized(y);
|
||||
| - value moved here
|
||||
...
|
||||
LL | println!("{}", &y);
|
||||
| ^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:30:24
|
||||
|
|
||||
LL | let y = *x;
|
||||
| -- value moved here
|
||||
LL | y.foo();
|
||||
LL | println!("{}", &x);
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `y`
|
||||
--> $DIR/borrow-after-move.rs:32:24
|
||||
|
|
||||
LL | y.foo();
|
||||
| - value moved here
|
||||
...
|
||||
LL | println!("{}", &y);
|
||||
| ^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:39:24
|
||||
|
|
||||
LL | x.foo();
|
||||
| - value moved here
|
||||
LL | println!("{}", &x);
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
42
src/test/ui/unsized-locals/borrow-after-move.rs
Normal file
42
src/test/ui/unsized-locals/borrow-after-move.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String;
|
||||
}
|
||||
|
||||
impl Foo for str {
|
||||
fn foo(self) -> String {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_unsized<T: ?Sized>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let y = *x;
|
||||
drop_unsized(y);
|
||||
println!("{}", &x);
|
||||
//~^ERROR use of moved value
|
||||
println!("{}", &y);
|
||||
//~^ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let y = *x;
|
||||
y.foo();
|
||||
println!("{}", &x);
|
||||
//~^ERROR use of moved value
|
||||
println!("{}", &y);
|
||||
//~^ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
x.foo();
|
||||
println!("{}", &x);
|
||||
//~^ERROR use of moved value
|
||||
}
|
||||
}
|
||||
57
src/test/ui/unsized-locals/borrow-after-move.stderr
Normal file
57
src/test/ui/unsized-locals/borrow-after-move.stderr
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:20:25
|
||||
|
|
||||
LL | let y = *x;
|
||||
| - value moved here
|
||||
LL | drop_unsized(y);
|
||||
LL | println!("{}", &x);
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/borrow-after-move.rs:22:25
|
||||
|
|
||||
LL | drop_unsized(y);
|
||||
| - value moved here
|
||||
...
|
||||
LL | println!("{}", &y);
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:30:25
|
||||
|
|
||||
LL | let y = *x;
|
||||
| - value moved here
|
||||
LL | y.foo();
|
||||
LL | println!("{}", &x);
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/borrow-after-move.rs:32:25
|
||||
|
|
||||
LL | y.foo();
|
||||
| - value moved here
|
||||
...
|
||||
LL | println!("{}", &y);
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/borrow-after-move.rs:39:25
|
||||
|
|
||||
LL | x.foo();
|
||||
| - value moved here
|
||||
LL | println!("{}", &x);
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
20
src/test/ui/unsized-locals/by-value-trait-object-safety.rs
Normal file
20
src/test/ui/unsized-locals/by-value-trait-object-safety.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String where Self: Sized;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl Foo for A {
|
||||
fn foo(self) -> String {
|
||||
format!("hello")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let x = *(Box::new(A) as Box<dyn Foo>);
|
||||
x.foo();
|
||||
//~^ERROR the `foo` method cannot be invoked on a trait object
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
error: the `foo` method cannot be invoked on a trait object
|
||||
--> $DIR/by-value-trait-object-safety.rs:18:7
|
||||
|
|
||||
LL | x.foo();
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
55
src/test/ui/unsized-locals/double-move.nll.stderr
Normal file
55
src/test/ui/unsized-locals/double-move.nll.stderr
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/double-move.rs:20:22
|
||||
|
|
||||
LL | drop_unsized(y);
|
||||
| - value moved here
|
||||
LL | drop_unsized(y); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/double-move.rs:26:22
|
||||
|
|
||||
LL | let _y = *x;
|
||||
| -- value moved here
|
||||
LL | drop_unsized(x); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:32:18
|
||||
|
|
||||
LL | drop_unsized(x);
|
||||
| - value moved here
|
||||
LL | let _y = *x; //~ERROR use of moved value
|
||||
| ^^ value used here after move
|
||||
|
||||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/double-move.rs:39:9
|
||||
|
|
||||
LL | y.foo();
|
||||
| - value moved here
|
||||
LL | y.foo(); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:45:9
|
||||
|
|
||||
LL | let _y = *x;
|
||||
| -- value moved here
|
||||
LL | x.foo(); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:51:18
|
||||
|
|
||||
LL | x.foo();
|
||||
| - value moved here
|
||||
LL | let _y = *x; //~ERROR use of moved value
|
||||
| ^^ value used here after move
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
53
src/test/ui/unsized-locals/double-move.rs
Normal file
53
src/test/ui/unsized-locals/double-move.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#![feature(unsized_locals)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(self) -> String;
|
||||
}
|
||||
|
||||
impl Foo for str {
|
||||
fn foo(self) -> String {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_unsized<T: ?Sized>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let y = *x;
|
||||
drop_unsized(y);
|
||||
drop_unsized(y); //~ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let _y = *x;
|
||||
drop_unsized(x); //~ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
drop_unsized(x);
|
||||
let _y = *x; //~ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let y = *x;
|
||||
y.foo();
|
||||
y.foo(); //~ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
let _y = *x;
|
||||
x.foo(); //~ERROR use of moved value
|
||||
}
|
||||
|
||||
{
|
||||
let x = "hello".to_owned().into_boxed_str();
|
||||
x.foo();
|
||||
let _y = *x; //~ERROR use of moved value
|
||||
}
|
||||
}
|
||||
63
src/test/ui/unsized-locals/double-move.stderr
Normal file
63
src/test/ui/unsized-locals/double-move.stderr
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/double-move.rs:20:22
|
||||
|
|
||||
LL | drop_unsized(y);
|
||||
| - value moved here
|
||||
LL | drop_unsized(y); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/double-move.rs:26:22
|
||||
|
|
||||
LL | let _y = *x;
|
||||
| -- value moved here
|
||||
LL | drop_unsized(x); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:32:13
|
||||
|
|
||||
LL | drop_unsized(x);
|
||||
| - value moved here
|
||||
LL | let _y = *x; //~ERROR use of moved value
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `y`
|
||||
--> $DIR/double-move.rs:39:9
|
||||
|
|
||||
LL | y.foo();
|
||||
| - value moved here
|
||||
LL | y.foo(); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `y` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:45:9
|
||||
|
|
||||
LL | let _y = *x;
|
||||
| -- value moved here
|
||||
LL | x.foo(); //~ERROR use of moved value
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value: `*x`
|
||||
--> $DIR/double-move.rs:51:13
|
||||
|
|
||||
LL | x.foo();
|
||||
| - value moved here
|
||||
LL | let _y = *x; //~ERROR use of moved value
|
||||
| ^^ value used here after move
|
||||
|
|
||||
= note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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(unsized_tuple_coercion, unsized_locals)]
|
||||
|
||||
struct A<X: ?Sized>(X);
|
||||
25
src/test/ui/unsized-locals/unsized-exprs.stderr
Normal file
25
src/test/ui/unsized-locals/unsized-exprs.stderr
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-exprs.rs:22:26
|
||||
|
|
||||
LL | udrop::<(i32, [u8])>((42, *foo()));
|
||||
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `({integer}, [u8])`, the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: required because it appears within the type `({integer}, [u8])`
|
||||
= note: tuples must have a statically known size to be initialized
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-exprs.rs:24:22
|
||||
|
|
||||
LL | udrop::<A<[u8]>>(A { 0: *foo() });
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `A<[u8]>`, the trait `std::marker::Sized` is not implemented for `[u8]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: required because it appears within the type `A<[u8]>`
|
||||
= note: structs must have a statically known size to be initialized
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
19
src/test/ui/unsized-locals/unsized-exprs2.nll.stderr
Normal file
19
src/test/ui/unsized-locals/unsized-exprs2.nll.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0508]: cannot move out of type `[u8]`, a non-copy slice
|
||||
--> $DIR/unsized-exprs2.rs:22:19
|
||||
|
|
||||
LL | udrop::<[u8]>(foo()[..]);
|
||||
| ^^^^^^^^^ cannot move out of here
|
||||
|
||||
error[E0507]: cannot move out of data in a `&` reference
|
||||
--> $DIR/unsized-exprs2.rs:22:19
|
||||
|
|
||||
LL | udrop::<[u8]>(foo()[..]);
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| cannot move out of data in a `&` reference
|
||||
| cannot move
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0507, E0508.
|
||||
For more information about an error, try `rustc --explain E0507`.
|
||||
|
|
@ -1,13 +1,3 @@
|
|||
// Copyright 2018 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(unsized_tuple_coercion, unsized_locals)]
|
||||
|
||||
struct A<X: ?Sized>(X);
|
||||
9
src/test/ui/unsized-locals/unsized-exprs2.stderr
Normal file
9
src/test/ui/unsized-locals/unsized-exprs2.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0507]: cannot move out of indexed content
|
||||
--> $DIR/unsized-exprs2.rs:22:19
|
||||
|
|
||||
LL | udrop::<[u8]>(foo()[..]);
|
||||
| ^^^^^^^^^ cannot move out of indexed content
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0507`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue