Skip to content

Commit b65ebc4

Browse files
author
Jorge Aparicio
committed
better document the hacks required to test libcollections
1 parent 8256241 commit b65ebc4

File tree

4 files changed

+133
-103
lines changed

4 files changed

+133
-103
lines changed

src/libcollections/macros.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ macro_rules! vec {
8484
($($x:expr,)*) => (vec![$($x),*])
8585
}
8686

87-
// HACK: `impl [T]` is not available in cfg(test), use `::slice::into_vec`, instead of
88-
// `<[T]>::to_vec`
87+
// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is required for this
88+
// macro definition, is not available. Instead use the `slice::into_vec` function which is only
89+
// available with cfg(test)
90+
// NB see the slice::hack module in slice.rs for more information
8991
#[cfg(not(stage0))]
9092
#[cfg(test)]
9193
macro_rules! vec {

src/libcollections/slice.rs

+116-95
Original file line numberDiff line numberDiff line change
@@ -1083,30 +1083,113 @@ impl<T> SliceExt for [T] {
10831083
}
10841084
}
10851085

1086-
// HACK: With cfg(test) `impl [T]` is not available, these three functions are actually methods
1087-
// that are in `impl [T]` but not in `core::slice::SliceExt` - this is only need for testing
1086+
// HACK(japaric) needed for the implementation of `vec!` macro during testing
1087+
// NB see the hack module in this file for more details
1088+
#[cfg(not(stage0))]
10881089
#[cfg(test)]
1089-
pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> {
1090-
unsafe {
1091-
let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len());
1092-
mem::forget(b);
1093-
xs
1094-
}
1095-
}
1090+
pub use self::hack::into_vec;
10961091

1092+
// HACK(japaric) needed for the implementation of `Vec::clone` during testing
1093+
// NB see the hack module in this file for more details
1094+
#[cfg(not(stage0))]
10971095
#[cfg(test)]
1098-
pub fn permutations<T>(s: &[T]) -> Permutations<T> where T: Clone {
1099-
Permutations{
1100-
swaps: ElementSwaps::new(s.len()),
1101-
v: ::slice::to_vec(s),
1096+
pub use self::hack::to_vec;
1097+
1098+
// HACK(japaric): With cfg(test) `impl [T]` is not available, these three functions are actually
1099+
// methods that are in `impl [T]` but not in `core::slice::SliceExt` - we need to supply these
1100+
// functions for the `test_permutations` test
1101+
#[cfg(not(stage0))]
1102+
mod hack {
1103+
use alloc::boxed::Box;
1104+
use core::clone::Clone;
1105+
#[cfg(test)]
1106+
use core::iter::{Iterator, IteratorExt};
1107+
use core::mem;
1108+
#[cfg(test)]
1109+
use core::option::Option::{Some, None};
1110+
1111+
#[cfg(test)]
1112+
use string::ToString;
1113+
use vec::Vec;
1114+
1115+
use super::{ElementSwaps, Permutations};
1116+
1117+
pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> {
1118+
unsafe {
1119+
let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len());
1120+
mem::forget(b);
1121+
xs
1122+
}
11021123
}
1103-
}
11041124

1105-
#[cfg(test)]
1106-
pub fn to_vec<T>(s: &[T]) -> Vec<T> where T: Clone {
1107-
let mut vector = Vec::with_capacity(s.len());
1108-
vector.push_all(s);
1109-
vector
1125+
pub fn permutations<T>(s: &[T]) -> Permutations<T> where T: Clone {
1126+
Permutations{
1127+
swaps: ElementSwaps::new(s.len()),
1128+
v: to_vec(s),
1129+
}
1130+
}
1131+
1132+
#[inline]
1133+
pub fn to_vec<T>(s: &[T]) -> Vec<T> where T: Clone {
1134+
let mut vector = Vec::with_capacity(s.len());
1135+
vector.push_all(s);
1136+
vector
1137+
}
1138+
1139+
// NB we can remove this hack if we move this test to libcollectionstest - but that can't be
1140+
// done right now because the test needs access to the private fields of Permutations
1141+
#[test]
1142+
fn test_permutations() {
1143+
{
1144+
let v: [i32; 0] = [];
1145+
let mut it = permutations(&v);
1146+
let (min_size, max_opt) = it.size_hint();
1147+
assert_eq!(min_size, 1);
1148+
assert_eq!(max_opt.unwrap(), 1);
1149+
assert_eq!(it.next(), Some(to_vec(&v)));
1150+
assert_eq!(it.next(), None);
1151+
}
1152+
{
1153+
let v = ["Hello".to_string()];
1154+
let mut it = permutations(&v);
1155+
let (min_size, max_opt) = it.size_hint();
1156+
assert_eq!(min_size, 1);
1157+
assert_eq!(max_opt.unwrap(), 1);
1158+
assert_eq!(it.next(), Some(to_vec(&v)));
1159+
assert_eq!(it.next(), None);
1160+
}
1161+
{
1162+
let v = [1, 2, 3];
1163+
let mut it = permutations(&v);
1164+
let (min_size, max_opt) = it.size_hint();
1165+
assert_eq!(min_size, 3*2);
1166+
assert_eq!(max_opt.unwrap(), 3*2);
1167+
assert_eq!(it.next().unwrap(), [1,2,3]);
1168+
assert_eq!(it.next().unwrap(), [1,3,2]);
1169+
assert_eq!(it.next().unwrap(), [3,1,2]);
1170+
let (min_size, max_opt) = it.size_hint();
1171+
assert_eq!(min_size, 3);
1172+
assert_eq!(max_opt.unwrap(), 3);
1173+
assert_eq!(it.next().unwrap(), [3,2,1]);
1174+
assert_eq!(it.next().unwrap(), [2,3,1]);
1175+
assert_eq!(it.next().unwrap(), [2,1,3]);
1176+
assert_eq!(it.next(), None);
1177+
}
1178+
{
1179+
// check that we have N! permutations
1180+
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
1181+
let mut amt = 0;
1182+
let mut it = permutations(&v);
1183+
let (min_size, max_opt) = it.size_hint();
1184+
for _perm in it.by_ref() {
1185+
amt += 1;
1186+
}
1187+
assert_eq!(amt, it.swaps.swaps_made);
1188+
assert_eq!(amt, min_size);
1189+
assert_eq!(amt, 2 * 3 * 4 * 5 * 6);
1190+
assert_eq!(amt, max_opt.unwrap());
1191+
}
1192+
}
11101193
}
11111194

11121195
#[cfg(not(stage0))]
@@ -1715,9 +1798,8 @@ impl<T> [T] {
17151798
#[stable(feature = "rust1", since = "1.0.0")]
17161799
#[inline]
17171800
pub fn to_vec(&self) -> Vec<T> where T: Clone {
1718-
let mut vector = Vec::with_capacity(self.len());
1719-
vector.push_all(self);
1720-
vector
1801+
// NB see hack module in this file
1802+
hack::to_vec(self)
17211803
}
17221804

17231805
/// Creates an iterator that yields every possible permutation of the
@@ -1745,11 +1827,10 @@ impl<T> [T] {
17451827
/// assert_eq!(Some(vec![3, 1, 2]), perms.next());
17461828
/// ```
17471829
#[unstable(feature = "collections")]
1830+
#[inline]
17481831
pub fn permutations(&self) -> Permutations<T> where T: Clone {
1749-
Permutations{
1750-
swaps: ElementSwaps::new(self.len()),
1751-
v: self.to_vec(),
1752-
}
1832+
// NB see hack module in this file
1833+
hack::permutations(self)
17531834
}
17541835

17551836
/// Copies as many elements from `src` as it can into `self` (the
@@ -1931,12 +2012,10 @@ impl<T> [T] {
19312012

19322013
/// Convert `self` into a vector without clones or allocation.
19332014
#[stable(feature = "rust1", since = "1.0.0")]
1934-
pub fn into_vec(mut self: Box<Self>) -> Vec<T> {
1935-
unsafe {
1936-
let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
1937-
mem::forget(self);
1938-
xs
1939-
}
2015+
#[inline]
2016+
pub fn into_vec(self: Box<Self>) -> Vec<T> {
2017+
// NB see hack module in this file
2018+
hack::into_vec(self)
19402019
}
19412020
}
19422021

@@ -2052,10 +2131,12 @@ impl<T: Clone> ToOwned for [T] {
20522131
#[cfg(not(test))]
20532132
fn to_owned(&self) -> Vec<T> { self.to_vec() }
20542133

2055-
// HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of
2056-
// `<[T]>::to_vec`
2134+
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec`, which is required for this method
2135+
// definition, is not available. Since we don't require this method for testing purposes, I'll
2136+
// just stub it
2137+
// NB see the slice::hack module in slice.rs for more information
20572138
#[cfg(test)]
2058-
fn to_owned(&self) -> Vec<T> { ::slice::to_vec(self) }
2139+
fn to_owned(&self) -> Vec<T> { panic!("not available with cfg(test)") }
20592140
}
20602141

20612142
////////////////////////////////////////////////////////////////////////////////
@@ -2372,63 +2453,3 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
23722453
old
23732454
}
23742455
}
2375-
2376-
#[cfg(test)]
2377-
mod test {
2378-
use core::iter::{Iterator, IteratorExt};
2379-
use core::option::Option::{None, Some};
2380-
use string::ToString;
2381-
2382-
#[test]
2383-
fn test_permutations() {
2384-
{
2385-
let v: [i32; 0] = [];
2386-
let mut it = ::slice::permutations(&v);
2387-
let (min_size, max_opt) = it.size_hint();
2388-
assert_eq!(min_size, 1);
2389-
assert_eq!(max_opt.unwrap(), 1);
2390-
assert_eq!(it.next(), Some(::slice::to_vec(&v)));
2391-
assert_eq!(it.next(), None);
2392-
}
2393-
{
2394-
let v = ["Hello".to_string()];
2395-
let mut it = ::slice::permutations(&v);
2396-
let (min_size, max_opt) = it.size_hint();
2397-
assert_eq!(min_size, 1);
2398-
assert_eq!(max_opt.unwrap(), 1);
2399-
assert_eq!(it.next(), Some(::slice::to_vec(&v)));
2400-
assert_eq!(it.next(), None);
2401-
}
2402-
{
2403-
let v = [1, 2, 3];
2404-
let mut it = ::slice::permutations(&v);
2405-
let (min_size, max_opt) = it.size_hint();
2406-
assert_eq!(min_size, 3*2);
2407-
assert_eq!(max_opt.unwrap(), 3*2);
2408-
assert_eq!(it.next().unwrap(), [1,2,3]);
2409-
assert_eq!(it.next().unwrap(), [1,3,2]);
2410-
assert_eq!(it.next().unwrap(), [3,1,2]);
2411-
let (min_size, max_opt) = it.size_hint();
2412-
assert_eq!(min_size, 3);
2413-
assert_eq!(max_opt.unwrap(), 3);
2414-
assert_eq!(it.next().unwrap(), [3,2,1]);
2415-
assert_eq!(it.next().unwrap(), [2,3,1]);
2416-
assert_eq!(it.next().unwrap(), [2,1,3]);
2417-
assert_eq!(it.next(), None);
2418-
}
2419-
{
2420-
// check that we have N! permutations
2421-
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
2422-
let mut amt = 0;
2423-
let mut it = ::slice::permutations(&v);
2424-
let (min_size, max_opt) = it.size_hint();
2425-
for _perm in it.by_ref() {
2426-
amt += 1;
2427-
}
2428-
assert_eq!(amt, it.swaps.swaps_made);
2429-
assert_eq!(amt, min_size);
2430-
assert_eq!(amt, 2 * 3 * 4 * 5 * 6);
2431-
assert_eq!(amt, max_opt.unwrap());
2432-
}
2433-
}
2434-
}

src/libcollections/string.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,14 @@ impl String {
118118
String { vec: <[_]>::to_vec(string.as_bytes()) }
119119
}
120120

121-
// HACK: `impl [T]` is not available in cfg(test), use `::slice::to_vec` instead of
122-
// `<[T]>::to_vec`
121+
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this
122+
// method definition, is not available. Since we don't require this method for testing
123+
// purposes, I'll just stub it
124+
// NB see the slice::hack module in slice.rs for more information
123125
#[inline]
124126
#[cfg(test)]
125-
pub fn from_str(string: &str) -> String {
126-
String { vec: ::slice::to_vec(string.as_bytes()) }
127+
pub fn from_str(_: &str) -> String {
128+
panic!("not available with cfg(test)");
127129
}
128130

129131
/// Returns the vector as a string buffer, if possible, taking care not to

src/libcollections/vec.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1290,10 +1290,15 @@ impl<T:Clone> Clone for Vec<T> {
12901290
#[cfg(not(test))]
12911291
fn clone(&self) -> Vec<T> { <[T]>::to_vec(&**self) }
12921292

1293-
// HACK: `impl [T]` not available in cfg(test), use `::slice::to_vec` instead of `<[T]>::to_vec`
1293+
// HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is required for this
1294+
// method definition, is not available. Instead use the `slice::to_vec` function which is only
1295+
// available with cfg(test)
1296+
// NB see the slice::hack module in slice.rs for more information
12941297
#[cfg(not(stage0))]
12951298
#[cfg(test)]
1296-
fn clone(&self) -> Vec<T> { ::slice::to_vec(&**self) }
1299+
fn clone(&self) -> Vec<T> {
1300+
::slice::to_vec(&**self)
1301+
}
12971302

12981303
fn clone_from(&mut self, other: &Vec<T>) {
12991304
// drop anything in self that will not be overwritten

0 commit comments

Comments
 (0)