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;
|
||||
|
||||
/// Arithmetic operations required by bignums.
|
||||
pub trait FullOps {
|
||||
pub trait FullOps: Sized {
|
||||
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
|
||||
/// where `W` is the number of bits in `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 => {
|
||||
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) => {
|
||||
err.note(&format!("required so that the projection `{}` is well-formed",
|
||||
data));
|
||||
|
@ -106,9 +106,12 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// Not well classified or should be obvious from span.
|
||||
MiscObligation,
|
||||
|
||||
/// This is the trait reference from the given projection
|
||||
/// A slice or array is WF only if `T: Sized`
|
||||
SliceOrArrayElem,
|
||||
|
||||
/// A tuple is WF only if its middle elements are Sized
|
||||
TupleElem,
|
||||
|
||||
/// This is the trait reference from the given projection
|
||||
ProjectionWf(ty::ProjectionTy<'tcx>),
|
||||
|
||||
|
@ -1652,7 +1652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
|
||||
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
|
||||
ty::TyArray(..) | ty::TyTuple(..) | ty::TyClosure(..) |
|
||||
ty::TyArray(..) | ty::TyClosure(..) |
|
||||
ty::TyError => {
|
||||
// safe for everything
|
||||
Where(ty::Binder(Vec::new()))
|
||||
@ -1660,6 +1660,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
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) => {
|
||||
let sized_crit = def.sized_constraint(self.tcx());
|
||||
// (*) binder moved here
|
||||
|
@ -1761,8 +1761,8 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
|
||||
let tys : Vec<_> = tys.into_iter()
|
||||
.map(|ty| self.sized_constraint_for_ty(tcx, stack, ty))
|
||||
.flat_map(|ty| match ty.sty {
|
||||
ty::TyTuple(ref tys) => tys.clone(),
|
||||
_ => vec![ty]
|
||||
ty::TyTuple(ref tys) => tys.last().cloned(),
|
||||
_ => Some(ty)
|
||||
})
|
||||
.filter(|ty| *ty != tcx.types.bool)
|
||||
.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
|
||||
/// to generate all the predicates needed to validate that `ty0`
|
||||
/// 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::TyArray(subty, _) => {
|
||||
if !subty.has_escaping_regions() {
|
||||
let cause = self.cause(traits::SliceOrArrayElem);
|
||||
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) => { }
|
||||
self.require_sized(subty, traits::SliceOrArrayElem);
|
||||
}
|
||||
|
||||
ty::TyTuple(ref tys) => {
|
||||
if let Some((_last, rest)) = tys.split_last() {
|
||||
for elem in rest {
|
||||
self.require_sized(elem, traits::TupleElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyBox(_) |
|
||||
ty::TyTuple(_) |
|
||||
ty::TyRawPtr(_) => {
|
||||
// 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>>) {
|
||||
f5(&(*x1, 34));
|
||||
//~^ 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>>) {
|
||||
|
@ -14,9 +14,9 @@ trait T {}
|
||||
|
||||
fn f1<X: ?Sized>(x: &X) {
|
||||
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: (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) {
|
||||
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
|
||||
|
Loading…
Reference in New Issue
Block a user