Fix no_std CI Warnings and WASM Compatibility (#17049)

# Objective

- Resolve several warnings encountered when compiling for `no_std`
around `dead_code`
- Fix compatibility with `wasm32-unknown-unknown` when using `no_std`
(identified by Sachymetsu on
[Discord](https://discord.com/channels/691052431525675048/692572690833473578/1323365426901549097))

## Solution

- Removed some unused imports
- Added `allow(dead_code)` for certain private items when compiling on
`no_std`
- Fixed `bevy_app` and `bevy_tasks` compatibility with WASM when
compiling without `std` by appropriately importing `Box` and feature
gating panic unwinding

## Testing

- CI
This commit is contained in:
Zachary Harrold 2024-12-31 10:01:27 +11:00 committed by GitHub
parent b78efd339d
commit 5f42c9ab6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 55 additions and 18 deletions

View File

@ -10,7 +10,7 @@ use bevy_utils::Instant;
#[cfg(target_arch = "wasm32")]
use {
alloc::rc::Rc,
alloc::{boxed::Box, rc::Rc},
core::cell::RefCell,
wasm_bindgen::{prelude::*, JsCast},
};

View File

@ -1,12 +1,17 @@
#[cfg(feature = "alloc")]
use alloc::{collections::BTreeMap, vec::Vec};
use {
super::{Measured2d, Triangle2d},
alloc::{collections::BTreeMap, vec::Vec},
};
use core::cmp::Ordering;
use crate::Vec2;
use super::{Measured2d, Triangle2d};
#[cfg_attr(
not(feature = "alloc"),
expect(dead_code, reason = "this type is only used with the alloc feature")
)]
#[derive(Debug, Clone, Copy)]
enum Endpoint {
Left,
@ -20,12 +25,20 @@ enum Endpoint {
///
/// This is the order expected by the [`SweepLine`].
#[derive(Debug, Clone, Copy)]
#[cfg_attr(
not(feature = "alloc"),
allow(dead_code, reason = "this type is only used with the alloc feature")
)]
struct SweepLineEvent {
segment: Segment,
/// Type of the vertex (left or right)
endpoint: Endpoint,
}
impl SweepLineEvent {
#[cfg_attr(
not(feature = "alloc"),
allow(dead_code, reason = "this type is only used with the alloc feature")
)]
fn position(&self) -> Vec2 {
match self.endpoint {
Endpoint::Left => self.segment.left,
@ -51,6 +64,10 @@ impl Ord for SweepLineEvent {
}
/// Orders 2D points according to the order expected by the sweep line and event queue from -X to +X and then -Y to Y.
#[cfg_attr(
not(feature = "alloc"),
allow(dead_code, reason = "this type is only used with the alloc feature")
)]
fn xy_order(a: Vec2, b: Vec2) -> Ordering {
a.x.total_cmp(&b.x).then_with(|| a.y.total_cmp(&b.y))
}
@ -134,6 +151,10 @@ impl Ord for Segment {
}
/// Holds information about which segment is above and which is below a given [`Segment`]
#[cfg_attr(
not(feature = "alloc"),
expect(dead_code, reason = "this type is only used with the alloc feature")
)]
#[derive(Debug, Clone, Copy)]
struct SegmentOrder {
above: Option<usize>,
@ -241,6 +262,13 @@ impl<'a> SweepLine<'a> {
/// Test what side of the line through `p1` and `p2` `q` is.
///
/// The result will be `0` if the `q` is on the segment, negative for one side and positive for the other.
#[cfg_attr(
not(feature = "alloc"),
expect(
dead_code,
reason = "this function is only used with the alloc feature"
)
)]
#[inline(always)]
fn point_side(p1: Vec2, p2: Vec2, q: Vec2) -> f32 {
(p2.x - p1.x) * (q.y - p1.y) - (q.x - p1.x) * (p2.y - p1.y)

View File

@ -4,9 +4,6 @@ use assert_type_match::assert_type_match;
use bevy_reflect_derive::{impl_reflect, impl_reflect_opaque};
use glam::*;
#[cfg(not(feature = "std"))]
use alloc::format;
/// Reflects the given foreign type as an enum and asserts that the variants/fields match up.
macro_rules! reflect_enum {
($(#[$meta:meta])* enum $ident:ident { $($ty:tt)* } ) => {
@ -381,6 +378,7 @@ impl_reflect_opaque!(::glam::BVec4A(Debug, Default, Deserialize, Serialize));
#[cfg(test)]
mod tests {
use alloc::format;
use ron::{
ser::{to_string_pretty, PrettyConfig},
Deserializer,

View File

@ -1,11 +1,8 @@
use alloc::boxed::Box;
use alloc::{boxed::Box, vec::Vec};
use bevy_reflect_derive::impl_type_path;
use core::any::Any;
use smallvec::{Array as SmallArray, SmallVec};
#[cfg(not(feature = "std"))]
use alloc::{format, vec, vec::Vec};
use crate::{
self as bevy_reflect, utility::GenericTypeInfoCell, ApplyError, FromReflect, FromType,
Generics, GetTypeRegistration, List, ListInfo, ListIter, MaybeTyped, PartialReflect, Reflect,

View File

@ -8,7 +8,6 @@
//! [`async-executor`]: https://crates.io/crates/async-executor
//! [`edge-executor`]: https://crates.io/crates/edge-executor
pub use async_task::Task;
use core::{
fmt,
panic::{RefUnwindSafe, UnwindSafe},

View File

@ -198,7 +198,7 @@ impl TaskPool {
where
T: 'static + MaybeSend + MaybeSync,
{
#[cfg(all(target_arch = "wasm32", feature = "std"))]
#[cfg(target_arch = "wasm32")]
return Task::wrap_future(future);
#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
@ -210,7 +210,7 @@ impl TaskPool {
Task::new(task)
});
#[cfg(not(feature = "std"))]
#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
return {
let task = LOCAL_EXECUTOR.spawn(future);
// Loop until all tasks are done

View File

@ -14,11 +14,11 @@ use core::{
/// Tasks that panic get immediately canceled. Awaiting a canceled task also causes a panic.
#[derive(Debug)]
#[must_use = "Tasks are canceled when dropped, use `.detach()` to run them in the background."]
pub struct Task<T>(crate::executor::Task<T>);
pub struct Task<T>(async_task::Task<T>);
impl<T> Task<T> {
/// Creates a new task from a given `async_executor::Task`
pub fn new(task: crate::executor::Task<T>) -> Self {
pub fn new(task: async_task::Task<T>) -> Self {
Self(task)
}

View File

@ -1,7 +1,8 @@
use core::marker::PhantomData;
use std::thread::{self, ThreadId};
use crate::executor::{Executor, Task};
use crate::executor::Executor;
use async_task::Task;
use futures_lite::Future;
/// An executor that can only be ticked on the thread it was instantiated on. But

View File

@ -1,3 +1,4 @@
use alloc::boxed::Box;
use core::{
any::Any,
future::{Future, IntoFuture},
@ -59,7 +60,12 @@ impl<T> Future for Task<T> {
// NOTE: Propagating the panic here sorta has parity with the async_executor behavior.
// For those tasks, polling them after a panic returns a `None` which gets `unwrap`ed, so
// using `resume_unwind` here is essentially keeping the same behavior while adding more information.
#[cfg(feature = "std")]
Poll::Ready(Ok(Err(panic))) => std::panic::resume_unwind(panic),
#[cfg(not(feature = "std"))]
Poll::Ready(Ok(Err(_panic))) => {
unreachable!("catching a panic is only possible with std")
}
Poll::Ready(Err(_)) => panic!("Polled a task after it was cancelled"),
Poll::Pending => Poll::Pending,
}
@ -74,6 +80,14 @@ struct CatchUnwind<F: UnwindSafe>(#[pin] F);
impl<F: Future + UnwindSafe> Future for CatchUnwind<F> {
type Output = Result<F::Output, Panic>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
std::panic::catch_unwind(AssertUnwindSafe(|| self.project().0.poll(cx)))?.map(Ok)
let f = AssertUnwindSafe(|| self.project().0.poll(cx));
#[cfg(feature = "std")]
let result = std::panic::catch_unwind(f)?;
#[cfg(not(feature = "std"))]
let result = f();
result.map(Ok)
}
}