Sling Academy
Home/Rust/E0088 in Rust: Using types with infinite size is disallowed (recursive types without indirection)

E0088 in Rust: Using types with infinite size is disallowed (recursive types without indirection)

Last updated: January 06, 2025

When working with Rust, a common compilation error you might encounter is E0088: Using types with infinite size is disallowed. This error typically arises when you define recursive data structures without utilizing a level of indirection, which Rust requires to manage recursive types. This guide aims to explain the cause of this error and how to resolve it using indirection properly.

Understanding the Problem with Recursive Types

Recursive types can be structures or enums that refer to themselves directly or indirectly through one of their fields. Consider the following example that leads to the E0088 error:

struct Node {
    value: i32,
    next: Node, // Error: Recursive type without indirection
}

The code defines a struct Node with an integer value and another Node as next. At first glance, it seems you are defining a simple linked list. However, in its current form, next is another instance of Node, and since a Node can exist infinitely, Rust cannot compute the size at compile time. Because Rust has no ability to understand how much space is necessary for such a structure, it raises error E0088 to prevent this unsized struct from being compiled.

How to Fix Recursive Types with Indirection

To rectify this error, introduce a level of indirection using smart pointers—most commonly with Box or other types such as Rc or Arc.

Using Box for Indirection

Box is a smart pointer that allocates memory on the heap, providing a fixed-size data type on the stack pointing to dynamic content. By wrapping the recursive field in a Box, you provide Rust with a size-known type cause “node linking”. Here is the corrected example of a linked list:

struct Node {
    value: i32,
    next: Option,
}

In this corrected version, each Node optionally points to another Node instance wrapped in a Box. This allows Rust to handle the dynamic nature of the structure without running into infinite size during compilation. Option is utilized here to denote the potential absence of a next item, which is a typical pattern in linked lists.

Example Usage

Here’s how you might construct and utilize this linked list in Rust:

fn main() {
    let third = Node {
        value: 3,
        next: None,
    };

    let second = Node {
        value: 2,
        next: Some(Box::new(third)),
    };

    let first = Node {
        value: 1,
        next: Some(Box::new(second)),
    };

    let mut current = &first;
    while let Some(ref next_node) = current.next {
        println!("Value: {}", current.value);
        current = next_node;
    }
    println!("Value: {}", current.value);
}

This program constructs a simple linked list with three nodes and iterates through them from the first to the third, printing the value of each node.

Caveats of Linked Lists in Rust

The linked list is a commonly used example in programming languages to illustrate basic data structures and recursive types. However, in Rust, this data structure may not always be optimal due to Rust's focus on safety and performance. Developers might opt for alternatives like Vec or custom-tailored data structures for specific use cases. The decision should factor in the trade-offs between safety, complexity, and performance.

Conclusion

Unhandled recursive types lead to compile-time errors, such as E0088, in Rust. The key to resolving these errors is by utilizing a smart pointer that provides the necessary indirection, such as Box, which helps in managing memory on the heap while ensuring a fixed size on the stack. This approach resolves the infinite size issue by directing further nodes optionally through a pointer, thereby allowing you to safely and effectively manage complex data structures in Rust.

Next Article: E0090 in Rust: Box type is not permitted in certain constant expressions

Previous Article: E0087 in Rust: Too many lifetimes provided for a type alias or function

Series: Common Errors in Rust and How to Fix Them

Rust

You May Also Like

  • E0557 in Rust: Feature Has Been Removed or Is Unavailable in the Stable Channel
  • Network Protocol Handling Concurrency in Rust with async/await
  • Using the anyhow and thiserror Crates for Better Rust Error Tests
  • Rust - Investigating partial moves when pattern matching on vector or HashMap elements
  • Rust - Handling nested or hierarchical HashMaps for complex data relationships
  • Rust - Combining multiple HashMaps by merging keys and values
  • Composing Functionality in Rust Through Multiple Trait Bounds
  • E0437 in Rust: Unexpected `#` in macro invocation or attribute
  • Integrating I/O and Networking in Rust’s Async Concurrency
  • E0178 in Rust: Conflicting implementations of the same trait for a type
  • Utilizing a Reactor Pattern in Rust for Event-Driven Architectures
  • Parallelizing CPU-Intensive Work with Rust’s rayon Crate
  • Managing WebSocket Connections in Rust for Real-Time Apps
  • Downloading Files in Rust via HTTP for CLI Tools
  • Mocking Network Calls in Rust Tests with the surf or reqwest Crates
  • Rust - Designing advanced concurrency abstractions using generic channels or locks
  • Managing code expansion in debug builds with heavy usage of generics in Rust
  • Implementing parse-from-string logic for generic numeric types in Rust
  • Rust.- Refining trait bounds at implementation time for more specialized behavior