Skip to content

Commit

Permalink
Merge pull request #333 from asomers/reproducibility
Browse files Browse the repository at this point in the history
Fix nondeterministic code generation
  • Loading branch information
asomers authored Sep 10, 2021
2 parents 54b47ba + e2f5285 commit f145b2f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ task:
lint_script:
- rustup component add clippy
- cargo clippy $CARGO_ARGS --all-targets --workspace -- -D warnings
reproducibility_script:
- env RUSTFLAGS="--cfg reprocheck" cargo check $CARGO_ARGS --all-targets
minver_script:
- cargo update -Zminimal-versions
- cargo test $CARGO_ARGS
Expand Down
15 changes: 15 additions & 0 deletions mockall/tests/automock_multiple_lifetime_parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// vim: tw=80
//! Methods with multiple generic lifetime parameters should produce their
//! generated code deterministically.
//!
//! This test is designed to work with "--cfg reprocheck"

#![deny(warnings)]
#![allow(clippy::needless_lifetimes)]

use mockall::*;

#[automock]
trait Foo {
fn foo<'a, 'b, 'c, 'd, 'e, 'f>(&self, x: &'a &'b &'c &'d &'e &'f i32);
}
35 changes: 31 additions & 4 deletions mockall_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use cfg_if::cfg_if;
use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, format_ident, quote};
use std::{
collections::{HashMap, HashSet},
env,
hash::BuildHasherDefault
};
use syn::{
*,
Expand All @@ -34,6 +34,10 @@ use crate::mock_item::MockItem;
use crate::mock_item_struct::MockItemStruct;
use crate::mockable_item::MockableItem;

// Define deterministic aliases for these common types.
type HashMap<K, V> = std::collections::HashMap<K, V, BuildHasherDefault<std::collections::hash_map::DefaultHasher>>;
type HashSet<K> = std::collections::HashSet<K, BuildHasherDefault<std::collections::hash_map::DefaultHasher>>;

cfg_if! {
// proc-macro2's Span::unstable method requires the nightly feature, and it
// doesn't work in test mode.
Expand Down Expand Up @@ -126,7 +130,7 @@ fn deanonymize(literal_type: &mut Type) {
fn declosurefy(gen: &Generics, args: &Punctuated<FnArg, Token![,]>) ->
(Generics, Vec<FnArg>, Vec<TokenStream>)
{
let mut hm = HashMap::new();
let mut hm = HashMap::default();

let mut save_fn_types = |ident: &Ident, tpb: &TypeParamBound| {
if let TypeParamBound::Trait(tb) = tpb {
Expand Down Expand Up @@ -1033,7 +1037,7 @@ fn mock_it<M: Into<MockableItem>>(inputs: M) -> TokenStream
ts
}

fn do_mock(input: TokenStream) -> TokenStream
fn do_mock_once(input: TokenStream) -> TokenStream
{
let item: MockableStruct = match syn::parse2(input) {
Ok(mock) => mock,
Expand All @@ -1044,6 +1048,18 @@ fn do_mock(input: TokenStream) -> TokenStream
mock_it(item)
}

fn do_mock(input: TokenStream) -> TokenStream
{
cfg_if! {
if #[cfg(reprocheck)] {
let ts_a = do_mock_once(input.clone());
let ts_b = do_mock_once(input.clone());
assert_eq!(ts_a.to_string(), ts_b.to_string());
}
}
do_mock_once(input)
}

#[proc_macro]
pub fn mock(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
do_mock(input.into()).into()
Expand All @@ -1058,7 +1074,7 @@ pub fn automock(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream)
do_automock(attrs, input).into()
}

fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
fn do_automock_once(attrs: TokenStream, input: TokenStream) -> TokenStream {
let mut output = input.clone();
let attrs: Attrs = match parse2(attrs) {
Ok(a) => a,
Expand All @@ -1076,6 +1092,17 @@ fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
output
}

fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
cfg_if! {
if #[cfg(reprocheck)] {
let ts_a = do_automock_once(attrs.clone(), input.clone());
let ts_b = do_automock_once(attrs.clone(), input.clone());
assert_eq!(ts_a.to_string(), ts_b.to_string());
}
}
do_automock_once(attrs, input)
}

#[cfg(test)]
mod t {
use super::*;
Expand Down

0 comments on commit f145b2f

Please sign in to comment.