Skip to content

Commit 0a6dfc5

Browse files
committed
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.
1 parent babb5df commit 0a6dfc5

File tree

8 files changed

+46
-19
lines changed

8 files changed

+46
-19
lines changed

src/libcore/num/bignum.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use mem;
3333
use intrinsics;
3434

3535
/// Arithmetic operations required by bignums.
36-
pub trait FullOps {
36+
pub trait FullOps: Sized {
3737
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
3838
/// where `W` is the number of bits in `Self`.
3939
fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);

src/librustc/traits/error_reporting.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,11 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
764764
ObligationCauseCode::SliceOrArrayElem => {
765765
err.note("slice and array elements must have `Sized` type");
766766
}
767+
ObligationCauseCode::TupleElem => {
768+
err.fileline_note(
769+
cause_span,
770+
"tuple elements must have `Sized` type");
771+
}
767772
ObligationCauseCode::ProjectionWf(data) => {
768773
err.note(&format!("required so that the projection `{}` is well-formed",
769774
data));

src/librustc/traits/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,12 @@ pub enum ObligationCauseCode<'tcx> {
106106
/// Not well classified or should be obvious from span.
107107
MiscObligation,
108108

109-
/// This is the trait reference from the given projection
109+
/// A slice or array is WF only if `T: Sized`
110110
SliceOrArrayElem,
111111

112+
/// A tuple is WF only if its middle elements are Sized
113+
TupleElem,
114+
112115
/// This is the trait reference from the given projection
113116
ProjectionWf(ty::ProjectionTy<'tcx>),
114117

src/librustc/traits/select.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1652,14 +1652,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16521652
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
16531653
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
16541654
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
1655-
ty::TyArray(..) | ty::TyTuple(..) | ty::TyClosure(..) |
1655+
ty::TyArray(..) | ty::TyClosure(..) |
16561656
ty::TyError => {
16571657
// safe for everything
16581658
Where(ty::Binder(Vec::new()))
16591659
}
16601660

16611661
ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
16621662

1663+
ty::TyTuple(ref tys) => {
1664+
Where(ty::Binder(match tys.last() {
1665+
Some(ty) => vec![ty],
1666+
_ => vec![]
1667+
}))
1668+
}
1669+
16631670
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
16641671
let sized_crit = def.sized_constraint(self.tcx());
16651672
// (*) binder moved here

src/librustc/ty/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,8 +1761,8 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
17611761
let tys : Vec<_> = tys.into_iter()
17621762
.map(|ty| self.sized_constraint_for_ty(tcx, stack, ty))
17631763
.flat_map(|ty| match ty.sty {
1764-
ty::TyTuple(ref tys) => tys.clone(),
1765-
_ => vec![ty]
1764+
ty::TyTuple(ref tys) => tys.last().cloned(),
1765+
_ => Some(ty)
17661766
})
17671767
.filter(|ty| *ty != tcx.types.bool)
17681768
.collect();

src/librustc/ty/wf.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,22 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
280280
}
281281
}
282282

283+
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
284+
if !subty.has_escaping_regions() {
285+
let cause = self.cause(cause);
286+
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
287+
ty::BoundSized,
288+
subty) {
289+
Ok(trait_ref) => {
290+
self.out.push(
291+
traits::Obligation::new(cause,
292+
trait_ref.to_predicate()));
293+
}
294+
Err(ErrorReported) => { }
295+
}
296+
}
297+
}
298+
283299
/// Push new obligations into `out`. Returns true if it was able
284300
/// to generate all the predicates needed to validate that `ty0`
285301
/// is WF. Returns false if `ty0` is an unresolved type variable,
@@ -301,23 +317,18 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
301317

302318
ty::TySlice(subty) |
303319
ty::TyArray(subty, _) => {
304-
if !subty.has_escaping_regions() {
305-
let cause = self.cause(traits::SliceOrArrayElem);
306-
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
307-
ty::BoundSized,
308-
subty) {
309-
Ok(trait_ref) => {
310-
self.out.push(
311-
traits::Obligation::new(cause,
312-
trait_ref.to_predicate()));
313-
}
314-
Err(ErrorReported) => { }
320+
self.require_sized(subty, traits::SliceOrArrayElem);
321+
}
322+
323+
ty::TyTuple(ref tys) => {
324+
if let Some((_last, rest)) = tys.split_last() {
325+
for elem in rest {
326+
self.require_sized(elem, traits::TupleElem);
315327
}
316328
}
317329
}
318330

319331
ty::TyBox(_) |
320-
ty::TyTuple(_) |
321332
ty::TyRawPtr(_) => {
322333
// simple cases that are WF if their type args are WF
323334
}

src/test/compile-fail/unsized3.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
6060
fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
6161
f5(&(*x1, 34));
6262
//~^ ERROR `X: std::marker::Sized` is not satisfied
63+
//~^^ ERROR `X: std::marker::Sized` is not satisfied
6364
}
6465

6566
fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {

src/test/compile-fail/unsized6.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ trait T {}
1414

1515
fn f1<X: ?Sized>(x: &X) {
1616
let _: X; // <-- this is OK, no bindings created, no initializer.
17-
let _: (isize, (X, isize)); // same
17+
let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
1818
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
19-
let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
19+
let y: (isize, (X, usize)); //~ERROR `X: std::marker::Sized` is not satisfied
2020
}
2121
fn f2<X: ?Sized + T>(x: &X) {
2222
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied

0 commit comments

Comments
 (0)