@@ -2,6 +2,8 @@ use std::any::Any;
22use std:: sync:: { Arc , Weak } ;
33use std:: cell:: RefCell ;
44use std:: cmp:: PartialEq ;
5+ use std:: iter:: TrustedLen ;
6+ use std:: mem;
57
68#[ test]
79fn uninhabited ( ) {
@@ -85,3 +87,120 @@ fn eq() {
8587 assert ! ( !( x != x) ) ;
8688 assert_eq ! ( * x. 0 . borrow( ) , 0 ) ;
8789}
90+
91+ type Rc < T > = Arc < T > ;
92+
93+ const SHARED_ITER_MAX : u16 = 100 ;
94+
95+ fn assert_trusted_len < I : TrustedLen > ( _: & I ) { }
96+
97+ #[ test]
98+ fn shared_from_iter_normal ( ) {
99+ // Exercise the base implementation for non-`TrustedLen` iterators.
100+ {
101+ // `Filter` is never `TrustedLen` since we don't
102+ // know statically how many elements will be kept:
103+ let iter = ( 0 ..SHARED_ITER_MAX ) . filter ( |x| x % 2 == 0 ) . map ( Box :: new) ;
104+
105+ // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
106+ let vec = iter. clone ( ) . collect :: < Vec < _ > > ( ) ;
107+ let rc = iter. collect :: < Rc < [ _ ] > > ( ) ;
108+ assert_eq ! ( & * vec, & * rc) ;
109+
110+ // Clone a bit and let these get dropped.
111+ {
112+ let _rc_2 = rc. clone ( ) ;
113+ let _rc_3 = rc. clone ( ) ;
114+ let _rc_4 = Rc :: downgrade ( & _rc_3) ;
115+ }
116+ } // Drop what hasn't been here.
117+ }
118+
119+ #[ test]
120+ fn shared_from_iter_trustedlen_normal ( ) {
121+ // Exercise the `TrustedLen` implementation under normal circumstances
122+ // where `size_hint()` matches `(_, Some(exact_len))`.
123+ {
124+ let iter = ( 0 ..SHARED_ITER_MAX ) . map ( Box :: new) ;
125+ assert_trusted_len ( & iter) ;
126+
127+ // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
128+ let vec = iter. clone ( ) . collect :: < Vec < _ > > ( ) ;
129+ let rc = iter. collect :: < Rc < [ _ ] > > ( ) ;
130+ assert_eq ! ( & * vec, & * rc) ;
131+ assert_eq ! ( mem:: size_of:: <Box <u16 >>( ) * SHARED_ITER_MAX as usize , mem:: size_of_val( & * rc) ) ;
132+
133+ // Clone a bit and let these get dropped.
134+ {
135+ let _rc_2 = rc. clone ( ) ;
136+ let _rc_3 = rc. clone ( ) ;
137+ let _rc_4 = Rc :: downgrade ( & _rc_3) ;
138+ }
139+ } // Drop what hasn't been here.
140+
141+ // Try a ZST to make sure it is handled well.
142+ {
143+ let iter = ( 0 ..SHARED_ITER_MAX ) . map ( |_| ( ) ) ;
144+ let vec = iter. clone ( ) . collect :: < Vec < _ > > ( ) ;
145+ let rc = iter. collect :: < Rc < [ _ ] > > ( ) ;
146+ assert_eq ! ( & * vec, & * rc) ;
147+ assert_eq ! ( 0 , mem:: size_of_val( & * rc) ) ;
148+ {
149+ let _rc_2 = rc. clone ( ) ;
150+ let _rc_3 = rc. clone ( ) ;
151+ let _rc_4 = Rc :: downgrade ( & _rc_3) ;
152+ }
153+ }
154+ }
155+
156+ #[ test]
157+ #[ should_panic = "I've almost got 99 problems." ]
158+ fn shared_from_iter_trustedlen_panic ( ) {
159+ // Exercise the `TrustedLen` implementation when `size_hint()` matches
160+ // `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
161+ let iter = ( 0 ..SHARED_ITER_MAX )
162+ . map ( |val| {
163+ match val {
164+ 98 => panic ! ( "I've almost got 99 problems." ) ,
165+ _ => Box :: new ( val) ,
166+ }
167+ } ) ;
168+ assert_trusted_len ( & iter) ;
169+ let _ = iter. collect :: < Rc < [ _ ] > > ( ) ;
170+
171+ panic ! ( "I am unreachable." ) ;
172+ }
173+
174+ #[ test]
175+ fn shared_from_iter_trustedlen_no_fuse ( ) {
176+ // Exercise the `TrustedLen` implementation when `size_hint()` matches
177+ // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
178+ struct Iter ( std:: vec:: IntoIter < Option < Box < u8 > > > ) ;
179+
180+ unsafe impl TrustedLen for Iter { }
181+
182+ impl Iterator for Iter {
183+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
184+ ( 2 , Some ( 2 ) )
185+ }
186+
187+ type Item = Box < u8 > ;
188+
189+ fn next ( & mut self ) -> Option < Self :: Item > {
190+ self . 0 . next ( ) . flatten ( )
191+ }
192+ }
193+
194+ let vec = vec ! [
195+ Some ( Box :: new( 42 ) ) ,
196+ Some ( Box :: new( 24 ) ) ,
197+ None ,
198+ Some ( Box :: new( 12 ) ) ,
199+ ] ;
200+ let iter = Iter ( vec. into_iter ( ) ) ;
201+ assert_trusted_len ( & iter) ;
202+ assert_eq ! (
203+ & [ Box :: new( 42 ) , Box :: new( 24 ) ] ,
204+ & * iter. collect:: <Rc <[ _] >>( )
205+ ) ;
206+ }
0 commit comments