# Rerast cookbook Here we've got some examples of things you can do with rerast. If you've got any more examples, please feel free to send pull requests. ### Replace ```try!(something)``` with ```something?``` ```rust fn rule1>(r: Result) -> Result { replace!(r#try!(r) => r?); unreachable!() } ``` This will change: ```rust pub fn get_file_contents(filename: &std::path::Path) -> std::io::Result { let mut result = String::new(); use std::io::Read; try!(try!(std::fs::File::open(filename)).read_to_string(&mut result)); Ok(result) } ``` Into this: ```rust pub fn get_file_contents(filename: &std::path::Path) -> std::io::Result { let mut result = String::new(); use std::io::Read; std::fs::File::open(filename)?.read_to_string(&mut result)?; Ok(result) } ``` This rule also shows how to handle rules that have return statements in them. i.e. specify a return type for your rule function. ```unreachable!()``` can then be used to avoid having to construct an actual value. ### Use accessors instead of direct field access ```rust fn r(mut p: Point, x: i32, y: i32) { replace!(Point{ x: x, y: y } => Point::new(x, y)); replace!(p.x = x => p.set_x(x)); replace!(&mut p.x => p.get_mut_x()); replace!(p.x => p.get_x()); } ``` This will change: ```rust fn f1(point: Point, point_ref: &Point, mut_point_ref: &mut Point) { let p2 = Point { x: 1, y: 2 }; process_i32(point.x); mut_point_ref.x = 1; let x = &mut mut_point_ref.x; *x = 42; process_i32(point_ref.x); } ``` Into: ```rust fn f1(point: Point, point_ref: &Point, mut_point_ref: &mut Point) { let p2 = Point::new(1, 2); process_i32(point.get_x()); mut_point_ref.set_x(1); let x = mut_point_ref.get_mut_x(); *x = 42; process_i32(point_ref.get_x()); } ``` ### Remove the argument from a function [cargo-issue]: https://github.com/rust-lang/cargo/issues/5746 [cargo-pr]: https://github.com/rust-lang/cargo/pull/5752 This is a real world example from the Cargo project ([issue][cargo-issue], [PR][cargo-pr]). ```rust use cargotest::support::{ project, project_foo }; fn rule1(a: &'static str) { replace!(project("foo") => project_foo()); replace!(project(a) => project_foo().at(a)); } ``` Changes: ```rust let p = project("foo") .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) .build(); let _p2 = project("bar") .file("Cargo.toml", &basic_bin_manifest("bar")) .file("src/bar.rs", &main_file(r#""i am bar""#, &[])) .build(); ``` Into: ```rust let p = project_foo() .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) .build(); let _p2 = project_foo().at("bar") .file("Cargo.toml", &basic_bin_manifest("bar")) .file("src/bar.rs", &main_file(r#""i am bar""#, &[])) .build(); ``` When run like this: ```terminal cargo +nightly rerast --rules_file=rewrite.rs --force --targets tests --file tests/testsuite/main.rs ``` Afterwhich a simple search and replace can rename `project_foo` back to `project` and the argument can be dropped. ### Replace await! macro with .await Since await can only be used from within an async function, you'll need to delcare your rule function async. This cannot be done from the command line, so you'll need to create a rule file with the following contents: ``` async fn rule1(r: T) { replace!(await!(r) => r.await) } ``` ### Replace yield Since yield can only be used from within a generator, you'll need to delcare your replace rule inside a generator. For example: ``` fn r1(x: i32) { let _ = || { replace!(yield x => yield x + 1); }; } ```