Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler both suggests and forbids the use of the core module #26768

Closed
dgoldstein0 opened this issue Jul 4, 2015 · 3 comments
Closed

Compiler both suggests and forbids the use of the core module #26768

dgoldstein0 opened this issue Jul 4, 2015 · 3 comments

Comments

@dgoldstein0
Copy link

This is on Rust 1.1 stable.

I'm learning Rust right now, and decided a good way to start off would be to write a linked list. In the process, I decided to add a print_list function that would traverse my linked list and print out it's contents. This would probably be fine had I not made my list generic, but having done that, I started getting compiler errors about T not being core::fmt::Display.

$ cargo run
   Compiling linked_list v0.1.0 (file:///C:/Users/David/Documents/code/rust/link
ed_list)
src\main.rs:56:36: 56:58 error: the trait `core::fmt::Display` is not implemente
d for the type `T` [E0277]
src\main.rs:56                     println!("{}", (*node).borrow().value);
                                                  ^~~~~~~~~~~~~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:25: 2:56 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
src\main.rs:56:21: 56:60 note: expansion site
src\main.rs:56:36: 56:58 note: `T` cannot be formatted with the default formatte
r; try using `:?` instead if you are using a format string
src\main.rs:56                     println!("{}", (*node).borrow().value);
                                                  ^~~~~~~~~~~~~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:25: 2:56 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
src\main.rs:56:21: 56:60 note: expansion site
error: aborting due to previous error
Could not compile `linked_list`.

To learn more, run the command again with --verbose.

So I added the Display trait and imported the core crate, only to be told (after fixing tons of other type errors) "error: use of unstable library feature 'core'". Why did the compiler even suggest I use core, if it wasn't going to allow it? I also find it weird that built in code depends on core, but I myself am not allowed to use it.

Here's my (probably terrible) code, for reference, which can be used to reproduce this bug.

extern crate core;

use core::fmt::Display;
use std::cell::RefCell;
use std::rc::Rc;

struct LinkedList<T: Copy + Display> {
    head: Option<Rc<RefCell<Node<T>>>>,
    tail: Option<Rc<RefCell<Node<T>>>>,
    length: u32,
}

struct Node<T: Copy> {
    next: Option<Rc<RefCell<Node<T>>>>,
    prev: Option<Rc<RefCell<Node<T>>>>,
    value: T,
}

impl<T: Copy> Node<T> {
    fn new(val: &T) -> Node<T> {
        Node::<T> {
            next: None,
            prev: None,
            value: *val,
        }
    }
}

impl<T: Copy + Display> LinkedList<T> {
    fn new() -> LinkedList<T> {
        LinkedList::<T> {
            head: None,
            tail: None,
            length: 0,
        }
    }

    fn append(&mut self, value: &T) {
        let new_node = Rc::new(RefCell::new(Node::<T>::new(value)));

        match self.tail.clone() {
            None => {
                self.head = Some(new_node.clone());
            },
            Some (tail_node) => {
                (*tail_node).borrow_mut().next = Some(new_node.clone());
                (*new_node).borrow_mut().prev = Some(tail_node.clone());
            }
        }
        self.tail = Some(new_node);
        self.length = self.length + 1;
    }

    fn print_list(&self) {
        let mut next_node = self.head.clone();
        loop {
            match next_node {
                Some(node) => {
                    println!("{}", (*node).borrow().value);
                    next_node = (*node).borrow().next.clone();
                },
                None => return,
            }
        }
    }
}

fn main() {
    let mut list = LinkedList::<i32>::new();

    let vals = vec![3, 2, 1, 0];
    for v in &vals {
        list.append(v);
    }

    list.print_list();
    return;
}
@pmarcelll
Copy link
Contributor

It's a known issue, core::fmt::Display is reexport as std::fmt::Display (because core is unstable), but the compiler is not smart enough to suggest the "public" trait. This also happens with private traits.

Related issues:
#23355
#23224
#13065
#26635
#26454
#25358

@steveklabnik
Copy link
Member

yes, as @pmarcelll says, this is a dup.

Why did the compiler even suggest I use core, if it wasn't going to allow it?

Basicaly, re-exported types don't have the information stored with them that they've been re-exported, so they use their non-re-exported name. Fixing this is going to be a fairly big refactoring, from what I've heard.

I also find it weird that built in code depends on core, but I myself am not allowed to use it.

This is because it's not stable yet. If you used a nightly compiler, you'd be allowed to.

Anyway, I'm closing since this is a dup, but you're completely right that it is a big usability issue. Sorry for the confusion :/

@dgoldstein0
Copy link
Author

Thanks for the super quick response, and for the pointer to use it from std - that did the trick for me. Also glad to know the problem is on your radar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants