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);
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));
/// 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>),
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()))
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
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();
}
}
+ 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,
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
}
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>>) {
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