2222 max_complexity : Cell < f64 > ,
2323 search_space_complexity : Cell < f64 > ,
2424 has_inherent_complexity : bool ,
25- inherent_complexity : f64 ,
25+ inherent_complexity : Cell < f64 > ,
2626 _phantom : PhantomData < T > ,
2727}
2828impl < T , M > FixedLenVecMutator < T , M >
3232{
3333 #[ no_coverage]
3434 pub fn new_with_repeated_mutator ( mutator : M , len : usize ) -> Self {
35- Self :: new ( vec ! [ mutator; len] , true )
35+ Self :: new ( vec ! [ mutator; len] )
3636 }
3737}
3838
4141 T : Clone + ' static ,
4242 M : Mutator < T > ,
4343{
44+ /// Note: only use this function if you really know what you are doing!
45+ ///
46+ /// Create a `FixedLenVecMutator` using the given submutators.
47+ /// The complexity of the generated vectors will be only the sum of the
48+ /// complexities of their elements.
49+ ///
50+ /// This is not the default behaviour.
51+ /// Normally, a vector such as `[1u8, 2u8]` would have a complexity of `17`:
52+ /// `2 * 8` for the first two integers, and `+ 1` for the inherent
53+ /// complexity of the vector itself. If the vector contains elements with a
54+ /// minimum complexity of 0.0, then its length would also influence its
55+ /// complexity. For example, `[(), ()]` would have a complexity of `3.0`:
56+ /// `1` for the vector and `+ 2` for the length.
57+ ///
58+ /// By using this function to create the `FixedLenVecMutator`, we get rid
59+ /// of the "inherent" part of the vector complexity. For example, the vector
60+ /// `[1u8, 2u8]` will have a complexity of 16.0 and the vector `[[], []]`
61+ /// will have a complexity of 0.0.
62+ ///
63+ /// Note that *all mutators in a fuzz test must agree on the complexity of
64+ /// a value*. For example, if you are mutating a 2-tuple of vectors:
65+ /// `(Vec<u8>, Vec<u8>)` using two `FixedLenVecMutator`, then both must
66+ /// agree on whether to include the inherent complexity of the vectors or
67+ /// not. That is, given the value `([1, 2], [1, 2])`, it is an error to
68+ /// evaluate the complexity of the first vector as `16.0` and the complexity
69+ /// of the second vector as `17.0`.
4470 #[ no_coverage]
45- pub fn new ( mutators : Vec < M > , inherent_complexity : bool ) -> Self {
71+ pub fn new_without_inherent_complexity ( mutators : Vec < M > ) -> Self {
4672 assert ! ( !mutators. is_empty( ) ) ;
4773
4874 Self {
5278 min_complexity : Cell :: new ( std:: f64:: INFINITY ) ,
5379 max_complexity : Cell :: default ( ) ,
5480 search_space_complexity : Cell :: default ( ) ,
55- has_inherent_complexity : inherent_complexity,
56- inherent_complexity : 0. ,
81+ has_inherent_complexity : false ,
82+ inherent_complexity : Cell :: default ( ) ,
83+ _phantom : PhantomData ,
84+ }
85+ }
86+
87+ #[ no_coverage]
88+ pub fn new ( mutators : Vec < M > ) -> Self {
89+ assert ! ( !mutators. is_empty( ) ) ;
90+
91+ Self {
92+ rng : Rng :: default ( ) ,
93+ mutators,
94+ initialized : Cell :: new ( false ) ,
95+ min_complexity : Cell :: new ( std:: f64:: INFINITY ) ,
96+ max_complexity : Cell :: default ( ) ,
97+ search_space_complexity : Cell :: default ( ) ,
98+ has_inherent_complexity : true ,
99+ inherent_complexity : Cell :: default ( ) ,
57100 _phantom : PhantomData ,
58101 }
59102 }
@@ -213,6 +256,7 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T
213256 |cplx, m| cplx + m. global_search_space_complexity ( ) ,
214257 ) ;
215258 self . initialized . set ( true ) ;
259+ self . inherent_complexity . set ( inherent_complexity) ;
216260 self . min_complexity . set ( min_complexity) ;
217261 self . max_complexity . set ( max_complexity) ;
218262 self . search_space_complexity . set ( search_space_complexity) ;
@@ -304,7 +348,7 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T
304348 #[ doc( hidden) ]
305349 #[ no_coverage]
306350 fn complexity ( & self , _value : & Vec < T > , cache : & Self :: Cache ) -> f64 {
307- cache. sum_cplx + self . inherent_complexity
351+ cache. sum_cplx + self . inherent_complexity . get ( )
308352 }
309353
310354 #[ doc( hidden) ]
@@ -321,7 +365,7 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T
321365 fn random_arbitrary ( & self , max_cplx : f64 ) -> ( Vec < T > , f64 ) {
322366 let target_cplx = crate :: mutators:: gen_f64 ( & self . rng , 1.0 ..max_cplx) ;
323367 let ( v, sum_cplx) = self . new_input_with_complexity ( target_cplx) ;
324- ( v, sum_cplx + self . inherent_complexity )
368+ ( v, sum_cplx + self . inherent_complexity . get ( ) )
325369 }
326370
327371 #[ doc( hidden) ]
@@ -347,11 +391,11 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T
347391 let step = & mut step. crossover_steps [ choice] ;
348392 let old_el_cplx = self . mutators [ choice] . complexity ( & value[ choice] , & cache. inner [ choice] ) ;
349393 let current_cplx = self . complexity ( value, cache) ;
350- let max_el_cplx = current_cplx - old_el_cplx - self . inherent_complexity ;
394+ let max_el_cplx = current_cplx - old_el_cplx - self . inherent_complexity . get ( ) ;
351395 if let Some ( ( el, new_el_cplx) ) = step. get_next_subvalue ( subvalue_provider, max_el_cplx) && self . mutators [ choice] . is_valid ( el) {
352396 let mut el = el. clone ( ) ;
353397 std:: mem:: swap ( & mut value[ choice] , & mut el) ;
354- let cplx = cache. sum_cplx - old_el_cplx + new_el_cplx + self . inherent_complexity ;
398+ let cplx = cache. sum_cplx - old_el_cplx + new_el_cplx + self . inherent_complexity . get ( ) ;
355399 let token = UnmutateVecToken :: ReplaceElement ( choice, el) ;
356400 return Some ( ( token, cplx) ) ;
357401 }
@@ -364,7 +408,7 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Vec<T>> for FixedLenVecMutator<T
364408 let idcs = & idcs[ ..count] ;
365409 Some ( self . mutate_elements ( value, cache, idcs, current_cplx, max_cplx) )
366410 } else {
367- let spare_cplx = max_cplx - current_cplx - self . inherent_complexity ;
411+ let spare_cplx = max_cplx - current_cplx - self . inherent_complexity . get ( ) ;
368412 let idx = step. element_step % value. len ( ) ;
369413 step. element_step += 1 ;
370414 self . mutate_element ( value, cache, step, subvalue_provider, idx, current_cplx, spare_cplx)
0 commit comments