@@ -13,6 +13,8 @@ use super::{
13
13
ContractConditionsData , ContractConditionsHandler ,
14
14
} ;
15
15
16
+ const WRAPPER_ARG_PREFIX : & str = "_wrapper_arg_" ;
17
+
16
18
impl < ' a > ContractConditionsHandler < ' a > {
17
19
/// Create the body of a check function.
18
20
///
@@ -60,7 +62,11 @@ impl<'a> ContractConditionsHandler<'a> {
60
62
let wrapper_args = if let Some ( wrapper_call_args) =
61
63
inner. iter_mut ( ) . find_map ( |stmt| try_as_wrapper_call_args ( stmt, & wrapper_name) )
62
64
{
63
- let wrapper_args = make_wrapper_args ( wrapper_call_args. len ( ) , attr. len ( ) ) ;
65
+ let wrapper_args = make_wrapper_idents (
66
+ wrapper_call_args. len ( ) ,
67
+ attr. len ( ) ,
68
+ WRAPPER_ARG_PREFIX ,
69
+ ) ;
64
70
wrapper_call_args
65
71
. extend ( wrapper_args. clone ( ) . map ( |a| Expr :: Verbatim ( quote ! ( #a) ) ) ) ;
66
72
wrapper_args
@@ -124,20 +130,43 @@ impl<'a> ContractConditionsHandler<'a> {
124
130
125
131
/// Emit a modifies wrapper, possibly augmenting a prior, existing one.
126
132
///
127
- /// We only augment if this clause is a `modifies` clause. In that case we
128
- /// expand its signature with one new argument of type `&impl Arbitrary` for
129
- /// each expression in the clause.
133
+ /// We only augment if this clause is a `modifies` clause. Before,
134
+ /// we annotated the wrapper arguments with `impl kani::Arbitrary`,
135
+ /// so Rust would infer the proper types for each argument.
136
+ /// We want to remove the restriction that these arguments must
137
+ /// implement `kani::Arbitrary` for checking. Now, we annotate each
138
+ /// argument with a generic type parameter, so the compiler can
139
+ /// continue inferring the correct types.
130
140
pub fn emit_augmented_modifies_wrapper ( & mut self ) {
131
141
if let ContractConditionsData :: Modifies { attr } = & self . condition_type {
132
- let wrapper_args = make_wrapper_args ( self . annotated_fn . sig . inputs . len ( ) , attr. len ( ) ) ;
142
+ let wrapper_args = make_wrapper_idents (
143
+ self . annotated_fn . sig . inputs . len ( ) ,
144
+ attr. len ( ) ,
145
+ WRAPPER_ARG_PREFIX ,
146
+ ) ;
147
+ // Generate a unique type parameter identifier
148
+ let type_params = make_wrapper_idents (
149
+ self . annotated_fn . sig . inputs . len ( ) ,
150
+ attr. len ( ) ,
151
+ "WrapperArgType" ,
152
+ ) ;
133
153
let sig = & mut self . annotated_fn . sig ;
134
- for arg in wrapper_args. clone ( ) {
154
+ for ( arg, arg_type) in wrapper_args. clone ( ) . zip ( type_params) {
155
+ // Add the type parameter to the function signature's generic parameters list
156
+ sig. generics . params . push ( syn:: GenericParam :: Type ( syn:: TypeParam {
157
+ attrs : vec ! [ ] ,
158
+ ident : arg_type. clone ( ) ,
159
+ colon_token : None ,
160
+ bounds : Default :: default ( ) ,
161
+ eq_token : None ,
162
+ default : None ,
163
+ } ) ) ;
135
164
let lifetime = syn:: Lifetime { apostrophe : Span :: call_site ( ) , ident : arg. clone ( ) } ;
136
165
sig. inputs . push ( FnArg :: Typed ( syn:: PatType {
137
166
attrs : vec ! [ ] ,
138
167
colon_token : Token ! [ : ] ( Span :: call_site ( ) ) ,
139
168
pat : Box :: new ( syn:: Pat :: Verbatim ( quote ! ( #arg) ) ) ,
140
- ty : Box :: new ( syn:: Type :: Verbatim ( quote ! ( & #lifetime impl kani :: Arbitrary ) ) ) ,
169
+ ty : Box :: new ( syn:: parse_quote! { & #arg_type } ) ,
141
170
} ) ) ;
142
171
sig. generics . params . push ( syn:: GenericParam :: Lifetime ( syn:: LifetimeParam {
143
172
lifetime,
@@ -146,6 +175,7 @@ impl<'a> ContractConditionsHandler<'a> {
146
175
attrs : vec ! [ ] ,
147
176
} ) ) ;
148
177
}
178
+
149
179
self . output . extend ( quote ! ( #[ kanitool:: modifies( #( #wrapper_args) , * ) ] ) )
150
180
}
151
181
self . emit_common_header ( ) ;
@@ -191,10 +221,14 @@ fn try_as_wrapper_call_args<'a>(
191
221
}
192
222
}
193
223
194
- /// Make `num` [`Ident`]s with the names `_wrapper_arg_ {i}` with `i` starting at `low` and
224
+ /// Make `num` [`Ident`]s with the names `prefix {i}` with `i` starting at `low` and
195
225
/// increasing by one each time.
196
- fn make_wrapper_args ( low : usize , num : usize ) -> impl Iterator < Item = syn:: Ident > + Clone {
197
- ( low..) . map ( |i| Ident :: new ( & format ! ( "_wrapper_arg_{i}" ) , Span :: mixed_site ( ) ) ) . take ( num)
226
+ fn make_wrapper_idents (
227
+ low : usize ,
228
+ num : usize ,
229
+ prefix : & ' static str ,
230
+ ) -> impl Iterator < Item = syn:: Ident > + Clone + ' static {
231
+ ( low..) . map ( move |i| Ident :: new ( & format ! ( "{prefix}{i}" ) , Span :: mixed_site ( ) ) ) . take ( num)
198
232
}
199
233
200
234
#[ cfg( test) ]
0 commit comments