|
7 | 7 | //! This is so we can keep [`super`] distraction-free as the definitions of data
|
8 | 8 | //! structures and the entry point for contract handling.
|
9 | 9 |
|
10 |
| -use std::collections::{HashMap, HashSet}; |
| 10 | +use std::collections::HashMap; |
11 | 11 |
|
12 | 12 | use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
|
13 | 13 | use quote::{quote, ToTokens};
|
14 | 14 | use std::hash::{DefaultHasher, Hash, Hasher};
|
15 | 15 | use syn::{
|
16 |
| - spanned::Spanned, visit::Visit, visit_mut::VisitMut, Attribute, Expr, ExprCall, ExprClosure, |
17 |
| - ExprPath, Path, |
| 16 | + spanned::Spanned, visit_mut::VisitMut, Attribute, Expr, ExprCall, ExprClosure, ExprPath, Path, |
18 | 17 | };
|
19 | 18 |
|
20 | 19 | use super::{ContractConditionsHandler, ContractFunctionState, INTERNAL_RESULT_IDENT};
|
@@ -102,26 +101,6 @@ pub fn identifier_for_generated_function(
|
102 | 101 | Ident::new(&identifier, proc_macro2::Span::mixed_site())
|
103 | 102 | }
|
104 | 103 |
|
105 |
| -/// We make shallow copies of the argument for the postconditions in both |
106 |
| -/// `requires` and `ensures` clauses and later clean them up. |
107 |
| -/// |
108 |
| -/// This function creates the code necessary to both make the copies (first |
109 |
| -/// tuple elem) and to clean them (second tuple elem). |
110 |
| -pub fn make_unsafe_argument_copies( |
111 |
| - renaming_map: &HashMap<Ident, Ident>, |
112 |
| -) -> (TokenStream2, TokenStream2) { |
113 |
| - let arg_names = renaming_map.values(); |
114 |
| - let also_arg_names = renaming_map.values(); |
115 |
| - let arg_values = renaming_map.keys(); |
116 |
| - ( |
117 |
| - quote!(#(let #arg_names = kani::internal::untracked_deref(&#arg_values);)*), |
118 |
| - #[cfg(not(feature = "no_core"))] |
119 |
| - quote!(#(std::mem::forget(#also_arg_names);)*), |
120 |
| - #[cfg(feature = "no_core")] |
121 |
| - quote!(#(core::mem::forget(#also_arg_names);)*), |
122 |
| - ) |
123 |
| -} |
124 |
| - |
125 | 104 | /// Used as the "single source of truth" for [`try_as_result_assign`] and [`try_as_result_assign_mut`]
|
126 | 105 | /// since we can't abstract over mutability. Input is the object to match on and the name of the
|
127 | 106 | /// function used to convert an `Option<LocalInit>` into the result type (e.g. `as_ref` and `as_mut`
|
@@ -184,28 +163,20 @@ pub fn try_as_result_assign_mut(stmt: &mut syn::Stmt) -> Option<&mut syn::LocalI
|
184 | 163 | /// When a `#[kani::ensures(|result|expr)]` is expanded, this function is called on with `build_ensures(|result|expr)`.
|
185 | 164 | /// This function goes through the expr and extracts out all the `old` expressions and creates a sequence
|
186 | 165 | /// of statements that instantiate these expressions as `let remember_kani_internal_x = old_expr;`
|
187 |
| -/// where x is a unique hash. This is returned as the first return parameter along with changing all the |
188 |
| -/// variables to `_renamed`. The second parameter is the closing of all the unsafe argument copies. The third |
189 |
| -/// return parameter is the expression formed by passing in the result variable into the input closure and |
190 |
| -/// changing all the variables to `_renamed`. |
191 |
| -pub fn build_ensures( |
192 |
| - fn_sig: &syn::Signature, |
193 |
| - data: &ExprClosure, |
194 |
| -) -> (TokenStream2, TokenStream2, Expr) { |
| 166 | +/// where x is a unique hash. This is returned as the first return parameter. The second |
| 167 | +/// return parameter is the expression formed by passing in the result variable into the input closure. |
| 168 | +pub fn build_ensures(data: &ExprClosure) -> (TokenStream2, Expr) { |
195 | 169 | let mut remembers_exprs = HashMap::new();
|
196 | 170 | let mut vis = OldVisitor { t: OldLifter::new(), remembers_exprs: &mut remembers_exprs };
|
197 | 171 | let mut expr = &mut data.clone();
|
198 | 172 | vis.visit_expr_closure_mut(&mut expr);
|
199 | 173 |
|
200 |
| - let arg_names = rename_argument_occurrences(fn_sig, &mut expr); |
201 |
| - let (start, end) = make_unsafe_argument_copies(&arg_names); |
202 |
| - |
203 | 174 | let remembers_stmts: TokenStream2 = remembers_exprs
|
204 | 175 | .iter()
|
205 |
| - .fold(start, |collect, (ident, expr)| quote!(let #ident = #expr; #collect)); |
| 176 | + .fold(quote!(), |collect, (ident, expr)| quote!(let #ident = #expr; #collect)); |
206 | 177 |
|
207 | 178 | let result: Ident = Ident::new(INTERNAL_RESULT_IDENT, Span::call_site());
|
208 |
| - (remembers_stmts, end, Expr::Verbatim(quote!((#expr)(&#result)))) |
| 179 | + (remembers_stmts, Expr::Verbatim(quote!((#expr)(&#result)))) |
209 | 180 | }
|
210 | 181 |
|
211 | 182 | trait OldTrigger {
|
@@ -304,76 +275,3 @@ impl OldTrigger for OldLifter {
|
304 | 275 | true
|
305 | 276 | }
|
306 | 277 | }
|
307 |
| - |
308 |
| -/// A supporting function for creating shallow, unsafe copies of the arguments |
309 |
| -/// for the postconditions. |
310 |
| -/// |
311 |
| -/// This function: |
312 |
| -/// - Collects all [`Ident`]s found in the argument patterns; |
313 |
| -/// - Creates new names for them; |
314 |
| -/// - Replaces all occurrences of those idents in `attrs` with the new names and; |
315 |
| -/// - Returns the mapping of old names to new names. |
316 |
| -fn rename_argument_occurrences( |
317 |
| - sig: &syn::Signature, |
318 |
| - attr: &mut ExprClosure, |
319 |
| -) -> HashMap<Ident, Ident> { |
320 |
| - let mut arg_ident_collector = ArgumentIdentCollector::new(); |
321 |
| - arg_ident_collector.visit_signature(&sig); |
322 |
| - |
323 |
| - let mk_new_ident_for = |id: &Ident| Ident::new(&format!("{}_renamed", id), Span::mixed_site()); |
324 |
| - let arg_idents = arg_ident_collector |
325 |
| - .0 |
326 |
| - .into_iter() |
327 |
| - .map(|i| { |
328 |
| - let new = mk_new_ident_for(&i); |
329 |
| - (i, new) |
330 |
| - }) |
331 |
| - .collect::<HashMap<_, _>>(); |
332 |
| - |
333 |
| - let mut ident_rewriter = Renamer(&arg_idents); |
334 |
| - ident_rewriter.visit_expr_closure_mut(attr); |
335 |
| - arg_idents |
336 |
| -} |
337 |
| - |
338 |
| -/// Collect all named identifiers used in the argument patterns of a function. |
339 |
| -struct ArgumentIdentCollector(HashSet<Ident>); |
340 |
| - |
341 |
| -impl ArgumentIdentCollector { |
342 |
| - fn new() -> Self { |
343 |
| - Self(HashSet::new()) |
344 |
| - } |
345 |
| -} |
346 |
| - |
347 |
| -impl<'ast> Visit<'ast> for ArgumentIdentCollector { |
348 |
| - fn visit_pat_ident(&mut self, i: &'ast syn::PatIdent) { |
349 |
| - self.0.insert(i.ident.clone()); |
350 |
| - syn::visit::visit_pat_ident(self, i) |
351 |
| - } |
352 |
| - fn visit_receiver(&mut self, _: &'ast syn::Receiver) { |
353 |
| - self.0.insert(Ident::new("self", proc_macro2::Span::call_site())); |
354 |
| - } |
355 |
| -} |
356 |
| - |
357 |
| -/// Applies the contained renaming (key renamed to value) to every ident pattern |
358 |
| -/// and ident expr visited. |
359 |
| -struct Renamer<'a>(&'a HashMap<Ident, Ident>); |
360 |
| - |
361 |
| -impl<'a> VisitMut for Renamer<'a> { |
362 |
| - fn visit_expr_path_mut(&mut self, i: &mut syn::ExprPath) { |
363 |
| - if i.path.segments.len() == 1 { |
364 |
| - i.path |
365 |
| - .segments |
366 |
| - .first_mut() |
367 |
| - .and_then(|p| self.0.get(&p.ident).map(|new| p.ident = new.clone())); |
368 |
| - } |
369 |
| - } |
370 |
| - |
371 |
| - /// This restores shadowing. Without this we would rename all ident |
372 |
| - /// occurrences, but not rebinding location. This is because our |
373 |
| - /// [`Self::visit_expr_path_mut`] is scope-unaware. |
374 |
| - fn visit_pat_ident_mut(&mut self, i: &mut syn::PatIdent) { |
375 |
| - if let Some(new) = self.0.get(&i.ident) { |
376 |
| - i.ident = new.clone(); |
377 |
| - } |
378 |
| - } |
379 |
| -} |
0 commit comments