Amanieu / intrusive-rs

Intrusive collections for Rust
Apache License 2.0
423 stars 50 forks source link

Make intrusive_adapter generated constructor function const #36

Closed penberg closed 5 years ago

penberg commented 5 years ago

I have an adapter defined with the intrusive_adapter macro as follows:

intrusive_adapter!(pub ProcessAdapter = Rc<Process>: Process { link: LinkedListLink });

However, I am unable to construct a linked list with it for a static variable:

static mut RUNQUEUE: LinkedList<ProcessAdapter> = LinkedList::new(ProcessAdapter::new());

because the ProcessAdapter::new() function is not const:

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants

The following patch fixes the problem for me:

diff --git a/src/adapter.rs b/src/adapter.rs
index ccb0349..3b98873 100644
--- a/src/adapter.rs
+++ b/src/adapter.rs
@@ -175,6 +175,11 @@ macro_rules! intrusive_adapter {
         #[allow(dead_code)]
         impl<$($args $(: ?$bound)*),*> $name<$($args),*> $($where_)* {
             pub const NEW: Self = $name($crate::__core::marker::PhantomData);
+            #[cfg(feature = "nightly")]
+            pub const fn new() -> Self {
+                Self::NEW
+            }
+            #[cfg(not(feature = "nightly"))]
             pub fn new() -> Self {
                 Self::NEW
             }

However, it cause the following compilation warning:

warning: outlives requirements can be inferred
    --> src/rbtree.rs:1456:43
     |
1456 | pub enum Entry<'a, A: Adapter<Link = Link> + 'a> {
     |                                           ^^^^^ help: remove this bound
     |
note: lint level defined here
    --> src/lib.rs:275:9
     |
275  | #![warn(rust_2018_idioms)]
     |         ^^^^^^^^^^^^^^^^
     = note: `#[warn(explicit_outlives_requirements)]` implied by `#[warn(rust_2018_idioms)]`

which I am not sure how to fix, which is why I am submitting this as an issue rather than a pull request.

Amanieu commented 5 years ago

There's issues with const fn and generic bounds. You should just use ::NEW when you need a const constructor, that's what it is for.

penberg commented 5 years ago

@Amanieu Aah, thanks! I didn't see ::NEW mentioned in the API documentation, but perhaps I didn't look closely enough.