diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b882d982c1fe..572979d063d2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3956,6 +3956,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err }; + if let ty::FnDef(..) = ty.sty { + let fn_sig = ty.fn_sig(tcx); + if !tcx.features().unsized_locals { + // We want to remove some Sized bounds from std functions, + // but don't want to expose the removal to stable Rust. + // i.e. we don't want to allow + // + // ```rust + // drop as fn(str); + // ``` + // + // to work in stable even if the Sized bound on `drop` is relaxed. + for i in 0..fn_sig.inputs().skip_binder().len() { + let input = tcx.erase_late_bound_regions(&fn_sig.input(i)); + self.require_type_is_sized_deferred(input, expr.span, + traits::SizedArgumentType); + } + } + // Here we want to prevent struct constructors from returning unsized types. + // There were two cases this happened: fn pointer coercion in stable + // and usual function call in presense of unsized_locals. + let output = tcx.erase_late_bound_regions(&fn_sig.output()); + self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + } + // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. let substs = self.tables.borrow().node_substs(expr.hir_id); diff --git a/src/test/ui/issues/issue-30355.nll.stderr b/src/test/ui/issues/issue-30355.nll.stderr deleted file mode 100644 index fdf8157dcf83..000000000000 --- a/src/test/ui/issues/issue-30355.nll.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0161]: cannot move a value of type X: the size of X cannot be statically determined - --> $DIR/issue-30355.rs:15:6 - | -LL | &X(*Y) - | ^^^^^ - -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ - -error[E0508]: cannot move out of type `[u8]`, a non-copy slice - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ cannot move out of here - -error: aborting due to 3 previous errors - -Some errors occurred: E0161, E0508. -For more information about an error, try `rustc --explain E0161`. diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/issues/issue-30355.rs index ee19d0403189..8d5eac06c437 100644 --- a/src/test/ui/issues/issue-30355.rs +++ b/src/test/ui/issues/issue-30355.rs @@ -13,9 +13,7 @@ pub struct X([u8]); pub static Y: &'static X = { const Y: &'static [u8] = b""; &X(*Y) - //~^ ERROR cannot move out - //~^^ ERROR cannot move a - //~^^^ ERROR cannot move a + //~^ ERROR E0277 }; fn main() {} diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr index 7e843688035a..1b55f20e6b43 100644 --- a/src/test/ui/issues/issue-30355.stderr +++ b/src/test/ui/issues/issue-30355.stderr @@ -1,22 +1,14 @@ -error[E0161]: cannot move a value of type X: the size of X cannot be statically determined +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/issue-30355.rs:15:6 | LL | &X(*Y) - | ^^^^^ - -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined - --> $DIR/issue-30355.rs:15:8 + | ^ doesn't have a size known at compile-time | -LL | &X(*Y) - | ^^ + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature -error[E0507]: cannot move out of borrowed content - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ cannot move out of borrowed content +error: aborting due to previous error -error: aborting due to 3 previous errors - -Some errors occurred: E0161, E0507. -For more information about an error, try `rustc --explain E0161`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs index 0cf93c78c4ab..8ca88edcb6ad 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.rs +++ b/src/test/ui/unsized-locals/unsized-exprs.rs @@ -23,4 +23,6 @@ fn main() { //~^ERROR E0277 udrop::>(A { 0: *foo() }); //~^ERROR E0277 + udrop::>(A(*foo())); + //~^ERROR E0277 } diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index eb2016941770..0ca60e8dea0d 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -20,6 +20,17 @@ LL | udrop::>(A { 0: *foo() }); = 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 +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:26:22 + | +LL | udrop::>(A(*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 + = note: required because it appears within the type `A<[u8]>` + = note: the return type of a function must have a statically known size + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs index ae69893a8357..3fb5a002e0e3 100644 --- a/src/test/ui/unsized-locals/unsized-exprs2.rs +++ b/src/test/ui/unsized-locals/unsized-exprs2.rs @@ -21,6 +21,4 @@ impl std::ops::Add for A<[u8]> { fn main() { udrop::<[u8]>(foo()[..]); //~^ERROR cannot move out of indexed content - // FIXME: should be error - udrop::>(A(*foo())); }