Lift some Sized checks.
This commit is contained in:
parent
7f05304068
commit
e2b95cb70e
@ -1454,9 +1454,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
ObligationCauseCode::VariableType(_) => {
|
||||
err.note("all local variables must have a statically known size");
|
||||
if !self.tcx.features().unsized_locals {
|
||||
err.help("unsized locals are gated as an unstable feature");
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::SizedArgumentType => {
|
||||
err.note("all function arguments must have a statically known size");
|
||||
if !self.tcx.features().unsized_locals {
|
||||
err.help("unsized locals are gated as an unstable feature");
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::SizedReturnType => {
|
||||
err.note("the return type of a function must have a \
|
||||
|
@ -903,12 +903,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
);
|
||||
}
|
||||
self.check_rvalue(mir, rv, location);
|
||||
if !self.tcx().features().unsized_locals {
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: tcx.lang_items().sized_trait().unwrap(),
|
||||
substs: tcx.mk_substs_trait(place_ty, &[]),
|
||||
};
|
||||
self.prove_trait_ref(trait_ref, location.interesting());
|
||||
}
|
||||
}
|
||||
StatementKind::SetDiscriminant {
|
||||
ref place,
|
||||
variant_index,
|
||||
@ -962,6 +964,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
mir: &Mir<'tcx>,
|
||||
term: &Terminator<'tcx>,
|
||||
term_location: Location,
|
||||
errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
|
||||
) {
|
||||
debug!("check_terminator: {:?}", term);
|
||||
let tcx = self.tcx();
|
||||
@ -1041,7 +1044,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
&sig,
|
||||
);
|
||||
let sig = self.normalize(sig, term_location);
|
||||
self.check_call_dest(mir, term, &sig, destination, term_location);
|
||||
self.check_call_dest(mir, term, &sig, destination, term_location, errors_buffer);
|
||||
|
||||
self.prove_predicates(
|
||||
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
|
||||
@ -1115,6 +1118,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
destination: &Option<(Place<'tcx>, BasicBlock)>,
|
||||
term_location: Location,
|
||||
errors_buffer: &mut Option<&mut Vec<Diagnostic>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
match *destination {
|
||||
@ -1143,6 +1147,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
terr
|
||||
);
|
||||
}
|
||||
|
||||
// When `#![feature(unsized_locals)]` is not enabled,
|
||||
// this check is done at `check_local`.
|
||||
if self.tcx().features().unsized_locals {
|
||||
let span = term.source_info.span;
|
||||
self.ensure_place_sized(dest_ty, span, errors_buffer);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// FIXME(canndrew): This is_never should probably be an is_uninhabited
|
||||
@ -1309,14 +1320,26 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
LocalKind::Var | LocalKind::Temp => {}
|
||||
}
|
||||
|
||||
// When `#![feature(unsized_locals)]` is enabled, only function calls
|
||||
// are checked in `check_call_dest`.
|
||||
if !self.tcx().features().unsized_locals {
|
||||
let span = local_decl.source_info.span;
|
||||
let ty = local_decl.ty;
|
||||
self.ensure_place_sized(ty, span, errors_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_place_sized(&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
errors_buffer: &mut Option<&mut Vec<Diagnostic>>) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// Erase the regions from `ty` to get a global type. The
|
||||
// `Sized` bound in no way depends on precise regions, so this
|
||||
// shouldn't affect `is_sized`.
|
||||
let gcx = self.tcx().global_tcx();
|
||||
let erased_ty = gcx.lift(&self.tcx().erase_regions(&ty)).unwrap();
|
||||
let gcx = tcx.global_tcx();
|
||||
let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
|
||||
if !erased_ty.is_sized(gcx.at(span), self.param_env) {
|
||||
// in current MIR construction, all non-control-flow rvalue
|
||||
// expressions evaluate through `as_temp` or `into` a return
|
||||
@ -1838,7 +1861,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
location.statement_index += 1;
|
||||
}
|
||||
|
||||
self.check_terminator(mir, block_data.terminator(), location);
|
||||
self.check_terminator(mir, block_data.terminator(), location, &mut errors_buffer);
|
||||
self.check_iscleanup(mir, block_data);
|
||||
}
|
||||
}
|
||||
|
@ -961,8 +961,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
if let PatKind::Binding(_, _, ident, _) = p.node {
|
||||
let var_ty = self.assign(p.span, p.id, None);
|
||||
|
||||
if !self.fcx.tcx.features().unsized_locals {
|
||||
self.fcx.require_type_is_sized(var_ty, p.span,
|
||||
traits::VariableType(p.id));
|
||||
}
|
||||
|
||||
debug!("Pattern binding {} is assigned to {} with type {:?}",
|
||||
ident,
|
||||
@ -1048,7 +1050,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
// for simple cases like `fn foo(x: Trait)`,
|
||||
// where we would error once on the parameter as a whole, and once on the binding `x`.
|
||||
if arg.pat.simple_ident().is_none() {
|
||||
if arg.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals {
|
||||
fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::SizedArgumentType);
|
||||
}
|
||||
|
||||
|
36
src/test/compile-fail/unsized-locals/unsized-exprs.rs
Normal file
36
src/test/compile-fail/unsized-locals/unsized-exprs.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// 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);
|
||||
|
||||
fn udrop<T: ?Sized>(_x: T) {}
|
||||
fn foo() -> Box<[u8]> {
|
||||
Box::new(*b"foo")
|
||||
}
|
||||
fn tfoo() -> Box<(i32, [u8])> {
|
||||
Box::new((42, *b"foo"))
|
||||
}
|
||||
fn afoo() -> Box<A<[u8]>> {
|
||||
Box::new(A(*b"foo"))
|
||||
}
|
||||
|
||||
impl std::ops::Add<i32> for A<[u8]> {
|
||||
type Output = ();
|
||||
fn add(self, _rhs: i32) -> Self::Output {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
udrop::<(i32, [u8])>((42, *foo()));
|
||||
//~^ERROR E0277
|
||||
udrop::<A<[u8]>>(A { 0: *foo() });
|
||||
//~^ERROR E0277
|
||||
}
|
36
src/test/compile-fail/unsized-locals/unsized-exprs2.rs
Normal file
36
src/test/compile-fail/unsized-locals/unsized-exprs2.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// 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);
|
||||
|
||||
fn udrop<T: ?Sized>(_x: T) {}
|
||||
fn foo() -> Box<[u8]> {
|
||||
Box::new(*b"foo")
|
||||
}
|
||||
fn tfoo() -> Box<(i32, [u8])> {
|
||||
Box::new((42, *b"foo"))
|
||||
}
|
||||
fn afoo() -> Box<A<[u8]>> {
|
||||
Box::new(A(*b"foo"))
|
||||
}
|
||||
|
||||
impl std::ops::Add<i32> for A<[u8]> {
|
||||
type Output = ();
|
||||
fn add(self, _rhs: i32) -> Self::Output {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
udrop::<[u8]>(foo()[..]);
|
||||
//~^ERROR cannot move out of indexed content
|
||||
// FIXME: should be error
|
||||
udrop::<A<[u8]>>(A(*foo()));
|
||||
}
|
@ -8,6 +8,7 @@ LL | let x = t.get(); //~ ERROR the size for values of type
|
||||
= 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>
|
||||
= help: consider adding a `where <T as Get>::Value: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,7 @@ LL | fn f(p: Path) { }
|
||||
= 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 `std::path::Path`
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the trait bound `i32: Foo` is not satisfied
|
||||
--> $DIR/E0277.rs:27:5
|
||||
|
@ -7,6 +7,7 @@ LL | fn f(f: FnOnce()) {}
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,6 +7,7 @@ LL | &mut something
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[T]`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,7 @@ LL | fn foo(self) -> &'static i32 {
|
||||
= 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>
|
||||
= help: consider adding a `where Self: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,6 +7,7 @@ LL | fn _test(ref _p: str) {}
|
||||
= help: the trait `std::marker::Sized` is not implemented for `str`
|
||||
= 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: all function arguments must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,6 +7,7 @@ LL | pub fn example(ref s: str) {}
|
||||
= help: the trait `std::marker::Sized` is not implemented for `str`
|
||||
= 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: all function arguments must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,7 @@ LL | fn baz(_: Self::Target) where Self: Deref {}
|
||||
= 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>
|
||||
= help: consider adding a `where <Self as std::ops::Deref>::Target: std::marker::Sized` bound
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `(dyn std::string::ToString + 'static)` cannot be known at compilation time
|
||||
--> $DIR/issue-42312.rs:18:23
|
||||
@ -18,6 +19,7 @@ LL | pub fn f(_: ToString) {}
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::string::ToString + 'static)`
|
||||
= 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: all function arguments must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -7,6 +7,7 @@ LL | fn new_struct(r: A+'static)
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
|
||||
--> $DIR/issue-5883.rs:18:8
|
||||
|
@ -7,6 +7,7 @@ LL | fn foo(_x: K) {}
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -30,6 +30,7 @@ LL | let v = s[..2];
|
||||
= help: the trait `std::marker::Sized` is not implemented for `str`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/str-array-assignment.rs:19:17
|
||||
|
@ -7,6 +7,7 @@ LL | fn foo(_x: Foo + Send) {
|
||||
= help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + std::marker::Send + 'static)`
|
||||
= 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: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,7 @@ LL | let y: Y;
|
||||
= 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>
|
||||
= help: consider adding a `where Y: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:17:12
|
||||
@ -41,6 +42,7 @@ LL | let y: X;
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `Y` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:27:12
|
||||
@ -63,6 +65,7 @@ LL | let y: X = *x1;
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:34:9
|
||||
@ -74,6 +77,7 @@ LL | let y = *x2;
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:36:10
|
||||
@ -85,6 +89,7 @@ LL | let (y, z) = (*x3, 4);
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:40:9
|
||||
@ -96,6 +101,7 @@ LL | let y: X = *x1;
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:42:9
|
||||
@ -107,6 +113,7 @@ LL | let y = *x2;
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:44:10
|
||||
@ -118,6 +125,7 @@ LL | let (y, z) = (*x3, 4);
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:48:18
|
||||
@ -129,6 +137,7 @@ LL | fn g1<X: ?Sized>(x: X) {}
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:50:22
|
||||
@ -140,6 +149,7 @@ LL | fn g2<X: ?Sized + T>(x: X) {}
|
||||
= 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>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user