diff options
| -rw-r--r-- | src/librustc/traits/error_reporting.rs | 2 | ||||
| -rw-r--r-- | src/librustc/traits/select.rs | 36 | ||||
| -rw-r--r-- | src/librustc/ty/layout.rs | 10 | ||||
| -rw-r--r-- | src/librustc/ty/util.rs | 29 | ||||
| -rw-r--r-- | src/librustc_trans/glue.rs | 12 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-assign-3.rs | 48 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-coerce1.rs | 12 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-coerce2.rs | 10 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-coerce3.rs | 10 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-coerce4.rs | 8 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-deep-2.rs | 21 | ||||
| -rw-r--r-- | src/test/run-pass-valgrind/dst-dtor-1.rs | 3 | ||||
| -rw-r--r-- | src/test/run-pass-valgrind/dst-dtor-2.rs | 3 | ||||
| -rw-r--r-- | src/test/run-pass/dst-irrefutable-bind.rs | 10 | ||||
| -rw-r--r-- | src/test/run-pass/dst-raw.rs | 32 | ||||
| -rw-r--r-- | src/test/run-pass/dst-trait-tuple.rs | 110 | ||||
| -rw-r--r-- | src/test/run-pass/dst-tuple-sole.rs | 83 | ||||
| -rw-r--r-- | src/test/run-pass/dst-tuple.rs | 128 |
18 files changed, 549 insertions, 18 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 35de536223a..0bf0e21baaf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1060,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.note("slice and array elements must have `Sized` type"); } ObligationCauseCode::TupleElem => { - err.note("tuple elements must have `Sized` type"); + err.note("only the last element of a tuple may have a dynamically sized type"); } ObligationCauseCode::ProjectionWf(data) => { err.note(&format!("required so that the projection `{}` is well-formed", diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a66b6b86354..11169eefdaf 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1651,6 +1651,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { def_id_a == def_id_b } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + tys_a.len() == tys_b.len() + } + _ => false }; @@ -2617,6 +2622,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[inner_target])); } + // (.., T) -> (.., U). + (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { + assert_eq!(tys_a.len(), tys_b.len()); + + // The last field of the tuple has to exist. + let (a_last, a_mid) = if let Some(x) = tys_a.split_last() { + x + } else { + return Err(Unimplemented); + }; + let b_last = tys_b.last().unwrap(); + + // Check that the source tuple with the target's + // last element is a subtype of the target. + let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false); + let InferOk { obligations, .. } = + self.infcx.at(&obligation.cause, obligation.param_env) + .eq(target, new_tuple) + .map_err(|_| Unimplemented)?; + self.inferred_obligations.extend(obligations); + + // Construct the nested T: Unsize<U> predicate. + nested.push(tcx.predicate_for_trait_def( + obligation.param_env, + obligation.cause.clone(), + obligation.predicate.def_id(), + obligation.recursion_depth + 1, + a_last, + &[b_last])); + } + _ => bug!() }; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 12af56d5c3d..e1aa89078a3 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1220,12 +1220,16 @@ impl<'a, 'tcx> Layout { } ty::TyTuple(tys, _) => { - // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. - // See the univariant case below to learn how. + let kind = if tys.len() == 0 { + StructKind::AlwaysSizedUnivariant + } else { + StructKind::MaybeUnsizedUnivariant + }; + let st = Struct::new(dl, &tys.iter().map(|ty| ty.layout(tcx, param_env)) .collect::<Result<Vec<_>, _>>()?, - &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?; + &ReprOptions::default(), kind, ty)?; Univariant { variant: st, non_zero: false } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 98ef7918fef..df4bbad3859 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -317,15 +317,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { target: Ty<'tcx>) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); - while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) { - if a_def != b_def || !a_def.is_struct() { - break; - } - match a_def.struct_variant().fields.last() { - Some(f) => { - a = f.ty(self, a_substs); - b = f.ty(self, b_substs); - } + loop { + match (&a.sty, &b.sty) { + (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) + if a_def == b_def && a_def.is_struct() => { + if let Some(f) = a_def.struct_variant().fields.last() { + a = f.ty(self, a_substs); + b = f.ty(self, b_substs); + } else { + break; + } + }, + (&TyTuple(a_tys, _), &TyTuple(b_tys, _)) + if a_tys.len() == b_tys.len() => { + if let Some(a_last) = a_tys.last() { + a = a_last; + b = b_tys.last().unwrap(); + } else { + break; + } + }, _ => break, } } diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 367f0398fa8..c2f44c089a2 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -76,7 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf } assert!(!info.is_null()); match t.sty { - ty::TyAdt(def, substs) => { + ty::TyAdt(..) | ty::TyTuple(..) => { let ccx = bcx.ccx; // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we @@ -101,8 +101,14 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf // Recurse to get the size of the dynamically sized field (must be // the last field). - let last_field = def.struct_variant().fields.last().unwrap(); - let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field); + let field_ty = match t.sty { + ty::TyAdt(def, substs) => { + let last_field = def.struct_variant().fields.last().unwrap(); + monomorphize::field_ty(bcx.tcx(), substs, last_field) + }, + ty::TyTuple(tys, _) => tys.last().unwrap(), + _ => unreachable!(), + }; let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); // FIXME (#26403, #27023): We should be adding padding diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs new file mode 100644 index 00000000000..3c089edf001 --- /dev/null +++ b/src/test/compile-fail/dst-bad-assign-3.rs @@ -0,0 +1,48 @@ +// Copyright 2014 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. + +// Forbid assignment into a dynamically sized type. + +type Fat<T: ?Sized> = (isize, &'static str, T); +//~^ WARNING trait bounds are not (yet) enforced + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat<ToBar> = &mut (5, "some str", Bar1 {f :42}); + let z: Box<ToBar> = Box::new(Bar1 {f: 36}); + f5.2 = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected type `ToBar` + //~| found type `Bar1` + //~| expected trait ToBar, found struct `Bar1` + //~| ERROR `ToBar: std::marker::Sized` is not satisfied +} diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 9a3ea54a3a4..722ff8f25d6 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -29,4 +29,16 @@ pub fn main() { let f2: &Fat<Foo> = &f1; let f3: &Fat<Bar> = f2; //~^ ERROR `Foo: Bar` is not satisfied + + // Tuple with a vec of isize. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &([usize],) = f2; + //~^ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &(Bar,) = f2; + //~^ ERROR `Foo: Bar` is not satisfied } diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d6..9e92f649b2d 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -28,4 +28,14 @@ pub fn main() { let f1 = Fat { ptr: Foo }; let f2: &Fat<Foo> = &f1; let f3: &mut Fat<Bar> = f2; //~ ERROR mismatched types + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &mut ([isize],) = f2; //~ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &mut (Bar,) = f2; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 7bad3bd69d3..4dedae9331b 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -28,6 +28,16 @@ fn baz<'a>() { let f1 = Fat { ptr: Foo }; let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough let f3: &'a Fat<Bar> = f2; + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a ([isize],) = f2; + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a (Bar,) = f2; } pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 9d4d56cf791..2e78108a8de 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -22,4 +22,12 @@ pub fn main() { //~| expected type `&Fat<[isize; 3]>` //~| found type `&Fat<[isize]>` //~| expected array of 3 elements, found slice + + // Tuple with a vec of isizes. + let f1: &([isize],) = &([1, 2, 3],); + let f2: &([isize; 3],) = f1; + //~^ ERROR mismatched types + //~| expected type `&([isize; 3],)` + //~| found type `&([isize],)` + //~| expected array of 3 elements, found slice } diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs new file mode 100644 index 00000000000..831afd27153 --- /dev/null +++ b/src/test/compile-fail/dst-bad-deep-2.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). + +pub fn main() { + let f: ([isize; 3],) = ([5, 6, 7],); + let g: &([isize],) = &f; + let h: &(([isize],),) = &(*g,); + //~^ ERROR `[isize]: std::marker::Sized` is not satisfied +} diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 4af642a106c..00bfebb3f1e 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -28,7 +28,8 @@ struct Fat<T: ?Sized> { pub fn main() { { - let _x: Box<Fat<Trait>> = Box::<Fat<Foo>>::new(Fat { f: Foo }); + let _x: Box<(i32, Fat<Trait>)> = + Box::<(i32, Fat<Foo>)>::new((42, Fat { f: Foo })); } unsafe { assert!(DROP_RAN); diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index 283b8202b35..fa0c6c03225 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -25,7 +25,8 @@ struct Fat<T: ?Sized> { pub fn main() { { - let _x: Box<Fat<[Foo]>> = Box::<Fat<[Foo; 3]>>::new(Fat { f: [Foo, Foo, Foo] }); + let _x: Box<(Fat<[Foo]>,)> = + Box::<(Fat<[Foo; 3]>,)>::new((Fat { f: [Foo, Foo, Foo] },)); } unsafe { assert_eq!(DROP_RAN, 3); diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs index 9f8067f372a..bd6ad9207ad 100644 --- a/src/test/run-pass/dst-irrefutable-bind.rs +++ b/src/test/run-pass/dst-irrefutable-bind.rs @@ -21,4 +21,14 @@ fn main() { let slice = &[1,2,3]; let x = Test(&slice); let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; } diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 3a74626b029..c82cbd75044 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -45,6 +45,14 @@ pub fn main() { }; assert_eq!(r, 42); + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + // raw slice let a: *const [_] = &[1, 2, 3]; unsafe { @@ -72,6 +80,15 @@ pub fn main() { assert_eq!(len, 3); } + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + // all of the above with *mut let mut x = A { f: 42 }; let z: *mut Trait = &mut x; @@ -87,6 +104,13 @@ pub fn main() { }; assert_eq!(r, 42); + let mut p = (A { f: 42 },); + let o: *mut (Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + let a: *mut [_] = &mut [1, 2, 3]; unsafe { let b = (*a)[2]; @@ -110,4 +134,12 @@ pub fn main() { let len = (&*c).f.len(); assert_eq!(len, 3); } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } } diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs new file mode 100644 index 00000000000..ab60e95c74e --- /dev/null +++ b/src/test/run-pass/dst-trait-tuple.rs @@ -0,0 +1,110 @@ +// Copyright 2014 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. + + +#![allow(unused_features)] +#![feature(box_syntax)] + +type Fat<T: ?Sized> = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat<ToBar>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat<Fat<ToBar>>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<ToBar> = f2; + foo(f3); + let f4: &Fat<ToBar> = &f1; + foo(f4); + let f5: &Fat<ToBar> = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat<ToBar> = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box<ToBar> = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat<Fat<ToBar>> = f2; + baz(f3); + let f4: &Fat<Fat<ToBar>> = &f1; + baz(f4); + let f5: &Fat<Fat<ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs new file mode 100644 index 00000000000..d3901a7555f --- /dev/null +++ b/src/test/run-pass/dst-tuple-sole.rs @@ -0,0 +1,83 @@ +// Copyright 2014 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. + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +type Fat<T: ?Sized> = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs new file mode 100644 index 00000000000..130294feb6c --- /dev/null +++ b/src/test/run-pass/dst-tuple.rs @@ -0,0 +1,128 @@ +// Copyright 2014 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. + + +#![allow(unknown_features)] +#![feature(box_syntax)] + +type Fat<T: ?Sized> = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat<Fat<[isize]>>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat<Fat<[isize]>> = f2; + foo3(f3); + let f4: &Fat<Fat<[isize]>> = &f1; + foo3(f4); + let f5: &Fat<Fat<[isize]>> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box<Fat<[isize; 3]>> = box (5, "some str", [1, 2, 3]); + foo(&*f1); + let f2 : Box<Fat<[isize]>> = f1; + foo(&*f2); + + let f3 : Box<Fat<[isize]>> = + Box::<Fat<[_; 3]>>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} |
