diff --git a/benchmarks/benches/lens.rs b/benchmarks/benches/lens.rs
index 997ae7050bca5767f3023861748b48a41daa2892..3ce3e35f8aaae48fde168f9019100bb69a43cf3f 100644
--- a/benchmarks/benches/lens.rs
+++ b/benchmarks/benches/lens.rs
@@ -2,7 +2,7 @@
 extern crate criterion;
 
 use bevy::prelude::*;
-use bevy_tweening::*;
+use bevy_tweening::lens::*;
 use criterion::{black_box, Criterion};
 
 fn text_color_lens(c: &mut Criterion) {
@@ -24,7 +24,7 @@ fn text_color_lens(c: &mut Criterion) {
         },
     );
     c.bench_function("TextColorLens", |b| {
-        b.iter(|| lens.interpolate(&mut text, black_box(0.3)))
+        b.iter(|| lens.lerp(&mut text, black_box(0.3)))
     });
 }
 
@@ -35,7 +35,7 @@ fn transform_position_lens(c: &mut Criterion) {
     };
     let mut transform = Transform::identity();
     c.bench_function("TransformPositionLens", |b| {
-        b.iter(|| lens.interpolate(&mut transform, black_box(0.3)))
+        b.iter(|| lens.lerp(&mut transform, black_box(0.3)))
     });
 }
 
@@ -46,7 +46,7 @@ fn transform_rotation_lens(c: &mut Criterion) {
     };
     let mut transform = Transform::identity();
     c.bench_function("TransformRotationLens", |b| {
-        b.iter(|| lens.interpolate(&mut transform, black_box(0.3)))
+        b.iter(|| lens.lerp(&mut transform, black_box(0.3)))
     });
 }
 
@@ -57,7 +57,7 @@ fn transform_scale_lens(c: &mut Criterion) {
     };
     let mut transform = Transform::identity();
     c.bench_function("TransformScaleLens", |b| {
-        b.iter(|| lens.interpolate(&mut transform, black_box(0.3)))
+        b.iter(|| lens.lerp(&mut transform, black_box(0.3)))
     });
 }
 
diff --git a/benchmarks/src/lib.rs b/benchmarks/src/lib.rs
index ac513337cba0af7eaebc1fdd4cf781d0c39ef86c..38dcc14e98e07088276b095afddac2df9cacf624 100644
--- a/benchmarks/src/lib.rs
+++ b/benchmarks/src/lib.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::all)]
+
 #[cfg(test)]
 mod tests {
     #[test]
diff --git a/examples/sequence.rs b/examples/sequence.rs
index 0cefa6b2abe43ebb9f93d2bf8effbf2ee433341b..84858b512b2640a5d064bdca504e83897f51ac9a 100644
--- a/examples/sequence.rs
+++ b/examples/sequence.rs
@@ -42,7 +42,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
         color: Color::RED,
     };
     let text_style_blue = TextStyle {
-        font: font.clone(),
+        font,
         font_size: 50.0,
         color: Color::BLUE,
     };
@@ -63,7 +63,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
                     },
                     TextSection {
                         value: "0%".to_owned(),
-                        style: text_style_red.clone(),
+                        style: text_style_red,
                     },
                 ],
                 alignment: text_alignment,
@@ -84,7 +84,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
                     },
                     TextSection {
                         value: "0%".to_owned(),
-                        style: text_style_blue.clone(),
+                        style: text_style_blue,
                     },
                 ],
                 alignment: text_alignment,
@@ -188,11 +188,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
 }
 
 fn update_text(
-    // Note: need a QuerySet<> due to the "&mut Text" in both queries
-    mut query_text: QuerySet<(
-        QueryState<&mut Text, With<RedProgress>>,
-        QueryState<&mut Text, With<BlueProgress>>,
-    )>,
+    mut query_text_red: Query<&mut Text, (With<RedProgress>, Without<BlueProgress>)>,
+    mut query_text_blue: Query<&mut Text, (With<BlueProgress>, Without<RedProgress>)>,
     query_anim_red: Query<&Animator<Transform>, With<RedSprite>>,
     query_anim_blue: Query<&Animator<Transform>, With<BlueSprite>>,
     mut query_event: EventReader<TweenCompleted>,
@@ -205,17 +202,11 @@ fn update_text(
     let tween_blue = anim_blue.tweenable().unwrap();
     let progress_blue = tween_blue.progress();
 
-    // Use scopes to force-drop the mutable context before opening the next one
-    {
-        let mut q0 = query_text.q0();
-        let mut red_text = q0.single_mut();
-        red_text.sections[1].value = format!("{:5.1}%", progress_red * 100.).to_string();
-    }
-    {
-        let mut q1 = query_text.q1();
-        let mut blue_text = q1.single_mut();
-        blue_text.sections[1].value = format!("{:5.1}%", progress_blue * 100.).to_string();
-    }
+    let mut red_text = query_text_red.single_mut();
+    red_text.sections[1].value = format!("{:5.1}%", progress_red * 100.);
+
+    let mut blue_text = query_text_blue.single_mut();
+    blue_text.sections[1].value = format!("{:5.1}%", progress_blue * 100.);
 
     for ev in query_event.iter() {
         println!(
diff --git a/release.md b/release.md
new file mode 100644
index 0000000000000000000000000000000000000000..c29320a39e27bfaeb2934bb0ad0b8d88fa2297e9
--- /dev/null
+++ b/release.md
@@ -0,0 +1,11 @@
+# Release process
+
+- Update `CHANGELOG` with date and version
+- Update `Cargo.toml` with version
+- Update `README.md` and other images to point to github raw content at commit SHA1 of current HEAD
+- `cargo fmt --all`
+- `cargo build`
+- `cargo clippy --workspace --all-targets --all-features -- -D warnings`
+- `cargo test`
+- `cargo docs --no-deps`
+- `cargo +nightly build` (for `docs.rs`)
diff --git a/src/lib.rs b/src/lib.rs
index c5e20ed9faea6130bc6ebca1c61906a0df4080ea..a98631a14374138ab191ec21a975a8f22995a41c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -249,9 +249,9 @@ impl Default for EaseMethod {
     }
 }
 
-impl Into<EaseMethod> for EaseFunction {
-    fn into(self) -> EaseMethod {
-        EaseMethod::EaseFunction(self)
+impl From<EaseFunction> for EaseMethod {
+    fn from(ease_function: EaseFunction) -> Self {
+        EaseMethod::EaseFunction(ease_function)
     }
 }
 
diff --git a/src/tweenable.rs b/src/tweenable.rs
index a0ddd28c2e6044aef319705b6dc87d4dbb418601..bb3e4a61954fe12ca933a92a821de4bd5c720541 100644
--- a/src/tweenable.rs
+++ b/src/tweenable.rs
@@ -146,6 +146,11 @@ impl<T, U: Tweenable<T> + Send + Sync + 'static> IntoBoxDynTweenable<T> for U {
     }
 }
 
+/// Type of a callback invoked when a [`Tween`] has completed.
+///
+/// See [`Tween::set_completed()`] for usage.
+pub type CompletedCallback<T> = dyn Fn(Entity, &Tween<T>) + Send + Sync + 'static;
+
 /// Single tweening animation instance.
 pub struct Tween<T> {
     ease_function: EaseMethod,
@@ -154,7 +159,7 @@ pub struct Tween<T> {
     direction: TweeningDirection,
     times_completed: u32,
     lens: Box<dyn Lens<T> + Send + Sync + 'static>,
-    on_completed: Option<Box<dyn Fn(Entity, &Tween<T>) + Send + Sync + 'static>>,
+    on_completed: Option<Box<CompletedCallback<T>>>,
     event_data: Option<u64>,
 }
 
@@ -372,7 +377,7 @@ impl<T> Tweenable<T> for Tween<T> {
                 });
             }
             if let Some(cb) = &self.on_completed {
-                cb(entity, &self);
+                cb(entity, self);
             }
         }
 
@@ -1007,7 +1012,7 @@ mod tests {
         );
         let mut tracks = Tracks::new([tween1, tween2]);
         assert_eq!(tracks.duration(), Duration::from_secs_f32(1.)); // max(1., 0.8)
-        assert_eq!(tracks.is_looping(), false);
+        assert!(!tracks.is_looping());
 
         let mut transform = Transform::default();
 
@@ -1095,7 +1100,7 @@ mod tests {
         {
             let tweenable: &dyn Tweenable<Transform> = &delay;
             assert_eq!(tweenable.duration(), duration);
-            assert_eq!(tweenable.is_looping(), false);
+            assert!(!tweenable.is_looping());
             assert!(tweenable.progress().abs() < 1e-5);
         }