Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

E0277 "Sized is not implemented for the type [u8]", but my type does not have a [u8]

Tags:

rust

I'm making a Node tree. Here is the code:

use std::option::Option;
use std::path;

#[derive(Debug)]
enum NodeType {
    Binding((String, String)),
    Header,
    Include(path::Path),
    Raw(String),
}

#[derive(Debug)]
pub struct Node {
    node_type: NodeType,
}

impl Node {
    fn new() -> Node {
        Node { node_type: NodeType::Header }
    }
}

When I compile this, I get the following error:

error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
 --> src/main.rs:8:13
  |
8 |     Include(path::Path),
  |             ^^^^^^^^^^^ within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
  |
  = note: `[u8]` does not have a constant size known at compile-time
  = note: required because it appears within the type `std::path::Path`
  = note: only the last field of a struct may have a dynamically sized type

I searched for this error, but it seems to refer to an type where Sized is not implemented. Oddly, the error output says that [u8] does not implement Sized, but there's not even one u8 in my code. What could it be?

like image 799
Mateus Felipe Avatar asked Feb 09 '16 15:02

Mateus Felipe


1 Answers

The problem is that your NodeType enum contains a std::path::Path in its Include variant, but Path is an unsized type (because it contains a [u8] indirectly, and [u8] is unsized, hence the error you get).

To fix this, change the Include variant to contain either a &Path (if the node should borrow the path) or a PathBuf (if the node should own the path), or else change Node::new() to return Box<Node>.

Changing Include to contain a &Path requires adding a lifetime parameter to Node and to NodeType. The concrete lifetime may be static when the enum is not an Include.

The code below demonstrates how this would work. Note how there are two impl blocks for Node: the first one (impl Node<'static>) should contain all methods that don't use the lifetime parameter, while the second one (impl<'a> Node<'a>) should contain all methods that do use the lifetime parameter (that includes all methods with a self parameter).

use std::path;

#[derive(Debug)]
enum NodeType<'a> {
    Binding((String, String)),
    Header,
    Include(&'a path::Path),
    Raw(String),
}

#[derive(Debug)]
pub struct Node<'a> {
    node_type: NodeType<'a>,
}

impl Node<'static> {
    fn new() -> Node<'static> {
        Node { node_type: NodeType::Header }
    }
}

impl<'a> Node<'a> {
    fn include(path: &'a path::Path) -> Node<'a> {
        Node { node_type: NodeType::Include(path) }
    }
}
like image 162
Francis Gagné Avatar answered Nov 16 '22 01:11

Francis Gagné