require the non-last elements of a tuple to be Sized
This requirement appears to be missing from RFC1214, but is clearly necessary for translation. The last field of a tuple/enum remains in a state of limbo, compiling but causing an ICE when it is used - we should eventually fix that somehow. this is a [breaking-change] - a soundness fix - and requires a crater run.
This commit is contained in:
parent
babb5df529
commit
0a6dfc5177
@ -33,7 +33,7 @@ use mem;
|
|||||||
use intrinsics;
|
use intrinsics;
|
||||||
|
|
||||||
/// Arithmetic operations required by bignums.
|
/// Arithmetic operations required by bignums.
|
||||||
pub trait FullOps {
|
pub trait FullOps: Sized {
|
||||||
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
|
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
|
||||||
/// where `W` is the number of bits in `Self`.
|
/// where `W` is the number of bits in `Self`.
|
||||||
fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
|
fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
|
||||||
|
@ -764,6 +764,11 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
|
|||||||
ObligationCauseCode::SliceOrArrayElem => {
|
ObligationCauseCode::SliceOrArrayElem => {
|
||||||
err.note("slice and array elements must have `Sized` type");
|
err.note("slice and array elements must have `Sized` type");
|
||||||
}
|
}
|
||||||
|
ObligationCauseCode::TupleElem => {
|
||||||
|
err.fileline_note(
|
||||||
|
cause_span,
|
||||||
|
"tuple elements must have `Sized` type");
|
||||||
|
}
|
||||||
ObligationCauseCode::ProjectionWf(data) => {
|
ObligationCauseCode::ProjectionWf(data) => {
|
||||||
err.note(&format!("required so that the projection `{}` is well-formed",
|
err.note(&format!("required so that the projection `{}` is well-formed",
|
||||||
data));
|
data));
|
||||||
|
@ -106,9 +106,12 @@ pub enum ObligationCauseCode<'tcx> {
|
|||||||
/// Not well classified or should be obvious from span.
|
/// Not well classified or should be obvious from span.
|
||||||
MiscObligation,
|
MiscObligation,
|
||||||
|
|
||||||
/// This is the trait reference from the given projection
|
/// A slice or array is WF only if `T: Sized`
|
||||||
SliceOrArrayElem,
|
SliceOrArrayElem,
|
||||||
|
|
||||||
|
/// A tuple is WF only if its middle elements are Sized
|
||||||
|
TupleElem,
|
||||||
|
|
||||||
/// This is the trait reference from the given projection
|
/// This is the trait reference from the given projection
|
||||||
ProjectionWf(ty::ProjectionTy<'tcx>),
|
ProjectionWf(ty::ProjectionTy<'tcx>),
|
||||||
|
|
||||||
|
@ -1652,7 +1652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
|
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
|
||||||
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
|
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
|
||||||
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
|
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
|
||||||
ty::TyArray(..) | ty::TyTuple(..) | ty::TyClosure(..) |
|
ty::TyArray(..) | ty::TyClosure(..) |
|
||||||
ty::TyError => {
|
ty::TyError => {
|
||||||
// safe for everything
|
// safe for everything
|
||||||
Where(ty::Binder(Vec::new()))
|
Where(ty::Binder(Vec::new()))
|
||||||
@ -1660,6 +1660,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
|
ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
|
||||||
|
|
||||||
|
ty::TyTuple(ref tys) => {
|
||||||
|
Where(ty::Binder(match tys.last() {
|
||||||
|
Some(ty) => vec![ty],
|
||||||
|
_ => vec![]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||||
let sized_crit = def.sized_constraint(self.tcx());
|
let sized_crit = def.sized_constraint(self.tcx());
|
||||||
// (*) binder moved here
|
// (*) binder moved here
|
||||||
|
@ -1761,8 +1761,8 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
|
|||||||
let tys : Vec<_> = tys.into_iter()
|
let tys : Vec<_> = tys.into_iter()
|
||||||
.map(|ty| self.sized_constraint_for_ty(tcx, stack, ty))
|
.map(|ty| self.sized_constraint_for_ty(tcx, stack, ty))
|
||||||
.flat_map(|ty| match ty.sty {
|
.flat_map(|ty| match ty.sty {
|
||||||
ty::TyTuple(ref tys) => tys.clone(),
|
ty::TyTuple(ref tys) => tys.last().cloned(),
|
||||||
_ => vec![ty]
|
_ => Some(ty)
|
||||||
})
|
})
|
||||||
.filter(|ty| *ty != tcx.types.bool)
|
.filter(|ty| *ty != tcx.types.bool)
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -280,6 +280,22 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
|
||||||
|
if !subty.has_escaping_regions() {
|
||||||
|
let cause = self.cause(cause);
|
||||||
|
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
|
||||||
|
ty::BoundSized,
|
||||||
|
subty) {
|
||||||
|
Ok(trait_ref) => {
|
||||||
|
self.out.push(
|
||||||
|
traits::Obligation::new(cause,
|
||||||
|
trait_ref.to_predicate()));
|
||||||
|
}
|
||||||
|
Err(ErrorReported) => { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Push new obligations into `out`. Returns true if it was able
|
/// Push new obligations into `out`. Returns true if it was able
|
||||||
/// to generate all the predicates needed to validate that `ty0`
|
/// to generate all the predicates needed to validate that `ty0`
|
||||||
/// is WF. Returns false if `ty0` is an unresolved type variable,
|
/// is WF. Returns false if `ty0` is an unresolved type variable,
|
||||||
@ -301,23 +317,18 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
|
|||||||
|
|
||||||
ty::TySlice(subty) |
|
ty::TySlice(subty) |
|
||||||
ty::TyArray(subty, _) => {
|
ty::TyArray(subty, _) => {
|
||||||
if !subty.has_escaping_regions() {
|
self.require_sized(subty, traits::SliceOrArrayElem);
|
||||||
let cause = self.cause(traits::SliceOrArrayElem);
|
}
|
||||||
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
|
|
||||||
ty::BoundSized,
|
ty::TyTuple(ref tys) => {
|
||||||
subty) {
|
if let Some((_last, rest)) = tys.split_last() {
|
||||||
Ok(trait_ref) => {
|
for elem in rest {
|
||||||
self.out.push(
|
self.require_sized(elem, traits::TupleElem);
|
||||||
traits::Obligation::new(cause,
|
|
||||||
trait_ref.to_predicate()));
|
|
||||||
}
|
|
||||||
Err(ErrorReported) => { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::TyBox(_) |
|
ty::TyBox(_) |
|
||||||
ty::TyTuple(_) |
|
|
||||||
ty::TyRawPtr(_) => {
|
ty::TyRawPtr(_) => {
|
||||||
// simple cases that are WF if their type args are WF
|
// simple cases that are WF if their type args are WF
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
|
|||||||
fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
||||||
f5(&(*x1, 34));
|
f5(&(*x1, 34));
|
||||||
//~^ ERROR `X: std::marker::Sized` is not satisfied
|
//~^ ERROR `X: std::marker::Sized` is not satisfied
|
||||||
|
//~^^ ERROR `X: std::marker::Sized` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
||||||
|
@ -14,9 +14,9 @@ trait T {}
|
|||||||
|
|
||||||
fn f1<X: ?Sized>(x: &X) {
|
fn f1<X: ?Sized>(x: &X) {
|
||||||
let _: X; // <-- this is OK, no bindings created, no initializer.
|
let _: X; // <-- this is OK, no bindings created, no initializer.
|
||||||
let _: (isize, (X, isize)); // same
|
let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
|
||||||
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
|
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
|
||||||
let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
|
let y: (isize, (X, usize)); //~ERROR `X: std::marker::Sized` is not satisfied
|
||||||
}
|
}
|
||||||
fn f2<X: ?Sized + T>(x: &X) {
|
fn f2<X: ?Sized + T>(x: &X) {
|
||||||
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
|
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
|
||||||
|
Loading…
Reference in New Issue
Block a user