Skip to content

Commit

Permalink
Improve closure support
Browse files Browse the repository at this point in the history
  • Loading branch information
MrGVSV committed Nov 9, 2024
1 parent 26b514f commit b86e281
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
18 changes: 11 additions & 7 deletions bevy_lint/src/lints/borrowed_reborrowable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
//!
//! # Known Issues
//!
//! This lint does not currently support closures.
//! This lint does not currently support the `Fn` traits or function pointers.
//!
//! This means the following types will not be caught by the lint:
//!
//! - `impl FnOnce(&mut Commands)`
//! - `Box<dyn FnMut(&mut Commands)>`
//! - `fn(&mut Commands)`
//!
//! # Example
//!
Expand Down Expand Up @@ -75,14 +81,12 @@ impl<'tcx> LateLintPass<'tcx> for BorrowedReborrowable {
_: Span,
def_id: LocalDefId,
) {
// Closures are not currently supported, as `tcx.fn_sig()` crashes for them.
if let FnKind::Closure = kind {
return;
}

// We use `instantiate_identity` to discharge the binder since we don't
// mind using placeholders for any bound arguments
let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity();
let fn_sig = match kind {
FnKind::Closure => cx.tcx.closure_user_provided_sig(def_id).value,
_ => cx.tcx.fn_sig(def_id).instantiate_identity(),
};

let arg_names = cx.tcx.fn_arg_names(def_id);

Expand Down
26 changes: 26 additions & 0 deletions bevy_lint/tests/ui/borrowed_reborrowable/bug_174.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! This test tracks the bug reported in [#174]. When this starts failing, the bug has been fixed.
//!
//! [#174]: https://github.com/TheBevyFlock/bevy_cli/issues/174

//@check-pass

#![feature(register_tool)]
#![register_tool(bevy)]
#![deny(bevy::borrowed_reborrowable)]

use bevy::prelude::*;

fn main() {
let mut world = World::new();

closure_wrapper(world.commands(), |commands| commands.spawn_empty().id());
closure_wrapper2(world.commands(), |commands| commands.spawn_empty().id());
}

fn closure_wrapper(mut commands: Commands, f: impl FnOnce(&mut Commands) -> Entity) {
f(&mut commands);
}

fn closure_wrapper2(mut commands: Commands, f: fn(&mut Commands) -> Entity) {
f(&mut commands);
}
20 changes: 20 additions & 0 deletions bevy_lint/tests/ui/borrowed_reborrowable/closures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! This tests the `borrowed_reborrowable` lint, specifically when triggered on closure types.

#![feature(register_tool)]
#![register_tool(bevy)]
#![deny(bevy::borrowed_reborrowable)]

use bevy::prelude::*;

fn main() {
let mut world = World::new();
let mut commands = world.commands();

//~| HELP: use `Commands` instead
//~v ERROR: parameter takes `&mut Commands` instead of a re-borrowed `Commands`
let closure = |commands: &mut Commands| {
commands.spawn_empty();
};

closure(&mut commands);
}
14 changes: 14 additions & 0 deletions bevy_lint/tests/ui/borrowed_reborrowable/closures.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: parameter takes `&mut Commands` instead of a re-borrowed `Commands`
--> tests/ui/borrowed_reborrowable/closures.rs:15:20
|
15 | let closure = |commands: &mut Commands| {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `Commands` instead: `mut commands: bevy::prelude::Commands<'_, '_>`
|
note: the lint level is defined here
--> tests/ui/borrowed_reborrowable/closures.rs:5:9
|
5 | #![deny(bevy::borrowed_reborrowable)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

0 comments on commit b86e281

Please sign in to comment.