Auto merge of #88087 - jesyspa:issue-87935-box, r=jackh726
Check that a box expression's type is Sized This resolves [issue 87935](https://github.com/rust-lang/rust/issues/87935). This makes E0161 (move from an unsized rvalue) much less common. I've replaced the test to use [this case](https://github.com/rust-lang/rust/blob/master/src/test/ui/object-safety/object-safety-by-value-self-use.rs), when a boxed `dyn` trait is passed by value, but that isn't an error when `unsized_locals` is enabled. I think it may be possible to get rid of E0161 entirely by checking that case earlier, but I'm not sure if that's desirable?
This commit is contained in:
commit
1e3d632f8f
@ -4,11 +4,18 @@ Erroneous code example:
|
|||||||
|
|
||||||
```compile_fail,E0161
|
```compile_fail,E0161
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
trait Bar {
|
||||||
|
fn f(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bar for i32 {
|
||||||
|
fn f(self) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let array: &[isize] = &[1, 2, 3];
|
let b: Box<dyn Bar> = box (0 as i32);
|
||||||
let _x: Box<[isize]> = box *array;
|
b.f();
|
||||||
// error: cannot move a value of type [isize]: the size of [isize] cannot
|
// error: cannot move a value of type dyn Bar: the size of dyn Bar cannot
|
||||||
// be statically determined
|
// be statically determined
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -22,8 +29,17 @@ it around as usual. Example:
|
|||||||
```
|
```
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn f(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bar for i32 {
|
||||||
|
fn f(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let array: &[isize] = &[1, 2, 3];
|
let b: Box<dyn Bar> = box (0 as i32);
|
||||||
let _x: Box<&[isize]> = box array; // ok!
|
b.f();
|
||||||
|
// ok!
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -225,6 +225,8 @@ pub enum ObligationCauseCode<'tcx> {
|
|||||||
SizedReturnType,
|
SizedReturnType,
|
||||||
/// Yield type must be `Sized`.
|
/// Yield type must be `Sized`.
|
||||||
SizedYieldType,
|
SizedYieldType,
|
||||||
|
/// Box expression result type must be `Sized`.
|
||||||
|
SizedBoxType,
|
||||||
/// Inline asm operand type must be `Sized`.
|
/// Inline asm operand type must be `Sized`.
|
||||||
InlineAsmSized,
|
InlineAsmSized,
|
||||||
/// `[T, ..n]` implies that `T` must be `Copy`.
|
/// `[T, ..n]` implies that `T` must be `Copy`.
|
||||||
|
@ -1893,9 +1893,7 @@ fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
|
|||||||
|
|
||||||
// While this is located in `nll::typeck` this error is not
|
// While this is located in `nll::typeck` this error is not
|
||||||
// an NLL error, it's a required check to prevent creation
|
// an NLL error, it's a required check to prevent creation
|
||||||
// of unsized rvalues in certain cases:
|
// of unsized rvalues in a call expression.
|
||||||
// * operand of a box expression
|
|
||||||
// * callee in a call expression
|
|
||||||
diag.emit();
|
diag.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2072,6 +2072,9 @@ fn note_obligation_cause_code<T>(
|
|||||||
ObligationCauseCode::SizedYieldType => {
|
ObligationCauseCode::SizedYieldType => {
|
||||||
err.note("the yield type of a generator must have a statically known size");
|
err.note("the yield type of a generator must have a statically known size");
|
||||||
}
|
}
|
||||||
|
ObligationCauseCode::SizedBoxType => {
|
||||||
|
err.note("the type of a box expression must have a statically known size");
|
||||||
|
}
|
||||||
ObligationCauseCode::AssignmentLhsSized => {
|
ObligationCauseCode::AssignmentLhsSized => {
|
||||||
err.note("the left-hand-side of an assignment must have a statically known size");
|
err.note("the left-hand-side of an assignment must have a statically known size");
|
||||||
}
|
}
|
||||||
|
@ -313,6 +313,7 @@ fn check_expr_box(&self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx
|
|||||||
_ => NoExpectation,
|
_ => NoExpectation,
|
||||||
});
|
});
|
||||||
let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
|
let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
|
||||||
|
self.require_type_is_sized(referent_ty, expr.span, traits::SizedBoxType);
|
||||||
self.tcx.mk_box(referent_ty)
|
self.tcx.mk_box(referent_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let _x: Box<str> = box *"hello world";
|
let _x: Box<str> = box *"hello world";
|
||||||
//~^ ERROR E0161
|
//~^ ERROR E0277
|
||||||
//~^^ ERROR cannot move out of a shared reference
|
|
||||||
|
|
||||||
let array: &[isize] = &[1, 2, 3];
|
let array: &[isize] = &[1, 2, 3];
|
||||||
let _x: Box<[isize]> = box *array;
|
let _x: Box<[isize]> = box *array;
|
||||||
//~^ ERROR E0161
|
//~^ ERROR E0277
|
||||||
//~^^ ERROR cannot move out of type `[isize]`, a non-copy slice
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,21 @@
|
|||||||
error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
|
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||||
--> $DIR/dst-rvalue.rs:6:28
|
--> $DIR/dst-rvalue.rs:6:28
|
||||||
|
|
|
|
||||||
LL | let _x: Box<str> = box *"hello world";
|
LL | let _x: Box<str> = box *"hello world";
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
|
= note: the type of a box expression must have a statically known size
|
||||||
|
|
||||||
error[E0161]: cannot move a value of type [isize]: the size of [isize] cannot be statically determined
|
error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
|
||||||
--> $DIR/dst-rvalue.rs:11:32
|
--> $DIR/dst-rvalue.rs:10:32
|
||||||
|
|
|
|
||||||
LL | let _x: Box<[isize]> = box *array;
|
LL | let _x: Box<[isize]> = box *array;
|
||||||
| ^^^^^^
|
| ^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
||||||
error[E0507]: cannot move out of a shared reference
|
|
||||||
--> $DIR/dst-rvalue.rs:6:28
|
|
||||||
|
|
|
|
||||||
LL | let _x: Box<str> = box *"hello world";
|
= help: the trait `Sized` is not implemented for `[isize]`
|
||||||
| ^^^^^^^^^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
|
= note: the type of a box expression must have a statically known size
|
||||||
|
|
||||||
error[E0508]: cannot move out of type `[isize]`, a non-copy slice
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/dst-rvalue.rs:11:32
|
|
||||||
|
|
|
||||||
LL | let _x: Box<[isize]> = box *array;
|
|
||||||
| ^^^^^^
|
|
||||||
| |
|
|
||||||
| cannot move out of here
|
|
||||||
| move occurs because `*array` has type `[isize]`, which does not implement the `Copy` trait
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0161, E0507, E0508.
|
|
||||||
For more information about an error, try `rustc --explain E0161`.
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
|
||||||
--> $DIR/E0161.rs:22:9
|
--> $DIR/E0161.rs:29:5
|
||||||
|
|
|
|
||||||
LL | box *x;
|
LL | x.f();
|
||||||
| ^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
|
||||||
--> $DIR/E0161.rs:22:5
|
|
||||||
|
|
|
||||||
LL | box *x;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0161`.
|
|
@ -1,8 +1,8 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
|
||||||
--> $DIR/E0161.rs:22:9
|
--> $DIR/E0161.rs:29:5
|
||||||
|
|
|
|
||||||
LL | box *x;
|
LL | x.f();
|
||||||
| ^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
|
||||||
--> $DIR/E0161.rs:22:5
|
|
||||||
|
|
|
||||||
LL | box *x;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0161`.
|
|
@ -1,8 +1,8 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
|
||||||
--> $DIR/E0161.rs:22:9
|
--> $DIR/E0161.rs:29:5
|
||||||
|
|
|
|
||||||
LL | box *x;
|
LL | x.f();
|
||||||
| ^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
|
||||||
--> $DIR/E0161.rs:22:5
|
|
||||||
|
|
|
||||||
LL | box *x;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0161`.
|
|
@ -8,6 +8,10 @@
|
|||||||
//[edition]edition:2018
|
//[edition]edition:2018
|
||||||
//[zflagsul]compile-flags: -Z borrowck=migrate
|
//[zflagsul]compile-flags: -Z borrowck=migrate
|
||||||
//[editionul]edition:2018
|
//[editionul]edition:2018
|
||||||
|
//[migrateul] check-pass
|
||||||
|
//[nllul] check-pass
|
||||||
|
//[zflagsul] check-pass
|
||||||
|
//[editionul] check-pass
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![cfg_attr(nll, feature(nll))]
|
#![cfg_attr(nll, feature(nll))]
|
||||||
@ -16,12 +20,14 @@
|
|||||||
#![cfg_attr(zflagsul, feature(unsized_locals))]
|
#![cfg_attr(zflagsul, feature(unsized_locals))]
|
||||||
#![cfg_attr(nllul, feature(unsized_locals))]
|
#![cfg_attr(nllul, feature(unsized_locals))]
|
||||||
#![cfg_attr(editionul, feature(unsized_locals))]
|
#![cfg_attr(editionul, feature(unsized_locals))]
|
||||||
#![feature(box_syntax)]
|
|
||||||
|
|
||||||
fn foo(x: Box<[i32]>) {
|
trait Bar {
|
||||||
box *x;
|
fn f(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(x: Box<dyn Bar>) {
|
||||||
|
x.f();
|
||||||
//[migrate,nll,zflags,edition]~^ ERROR E0161
|
//[migrate,nll,zflags,edition]~^ ERROR E0161
|
||||||
//[migrateul,nllul,zflagsul,editionul]~^^ ERROR E0161
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
|
||||||
--> $DIR/E0161.rs:22:9
|
--> $DIR/E0161.rs:29:5
|
||||||
|
|
|
|
||||||
LL | box *x;
|
LL | x.f();
|
||||||
| ^^
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
error[E0161]: cannot move a value of type [i32]: the size of [i32] cannot be statically determined
|
|
||||||
--> $DIR/E0161.rs:22:5
|
|
||||||
|
|
|
||||||
LL | box *x;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0161`.
|
|
10
src/test/ui/typeck/issue-87935-unsized-box-expr.rs
Normal file
10
src/test/ui/typeck/issue-87935-unsized-box-expr.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#![feature(box_syntax)]
|
||||||
|
// Box expression needs to be movable, and hence has to be of a Sized type.
|
||||||
|
fn main() {
|
||||||
|
let _x: Box<[u32]> = box { loop {} };
|
||||||
|
//~^ ERROR: the size for values of type `[u32]` cannot be known at compilation time
|
||||||
|
|
||||||
|
// Check that a deduced size does not cause issues.
|
||||||
|
let _y: Box<[u32]> = box [];
|
||||||
|
let _z: Box<[u32; 0]> = box { loop {} };
|
||||||
|
}
|
12
src/test/ui/typeck/issue-87935-unsized-box-expr.stderr
Normal file
12
src/test/ui/typeck/issue-87935-unsized-box-expr.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
|
||||||
|
--> $DIR/issue-87935-unsized-box-expr.rs:4:30
|
||||||
|
|
|
||||||
|
LL | let _x: Box<[u32]> = box { loop {} };
|
||||||
|
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `[u32]`
|
||||||
|
= note: the type of a box expression must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user