'use' keyword not working (calling from sibling file) - rust

I'm trying to use a struct from a value.rs file from chunk.rs, but it is not working. This is my current file hierarchy.
src
|
|---value.rs
|---chunk.rs
|---other files
Here is my value.rs code:
pub enum Value {
}
pub struct ValueArray {
values: Vec<Value>,
}
pub impl Value {
pub fn new() -> Value {
Value {
values: Vec::new(),
}
}
pub fn write_chunk(&mut self, value: Value) {
self.code.push(value);
}
}
Here is my chunk.rs code:
use crate::value::ValueArray; // Error Here
pub enum OpCode {
OpReturn,
}
pub struct Chunk {
pub code: Vec<OpCode>,
constants: value::ValueArray,
}
impl Chunk {
pub fn new() -> Chunk {
Chunk {
code: Vec::new(),
constants: value::ValueArray::new(),
}
}
pub fn write_chunk(&mut self, byte: OpCode) {
self.code.push(byte);
}
}
This is my exact error message:
unresolved import `crate::value`
could not find `value` in the crate rootrustc(E0432)
chunk.rs(1, 12): could not find `value` in the crate root
I'm not sure why it isn't working since I've done something very similar in another sibling file. I'm new to Rust, so I appreciate all of your help. Thanks

You need to define the value module on the lib.rs file
pub mod value;

The syntax I'm using to include a file ("lib.rs") with naked structs/functions (no explicit module defined) is:
mod lib;
use crate::lib::*;
So you must be missing mod value;.

Related

Why can I write Guess{value:1000} when value is private?

I have a code like this from the offical tutorial book Chapter 9.3
#![allow(unused)]
fn main() {
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess { value }
}
pub fn value(&self) -> i32 {
self.value
}
}
let g = Guess{
value:1000
};
println!("{}", g.value);
}
According to the book I should not be able to create a Guess using the let g = Guess {} However, this code does not cause any error and prints 1000
There is still a problem even if I put the struct and impl outside the main func like this and delete the pub keyword.
struct Guess {}
impl Guess {}
fn main() {}
According to the book I should not be able to create a Guess using the let g = Guess {}
It is unlikely that the book states that.
Rust visibility works in terms of modules, anything in a module can see all the contents of their parents regardless of their pub status; the reverse is not true.
Since main and Guess.value are in the same module, there is no barrier. Moving Guess out of main doesn't change that, they're still in the same module. For visibility to become an issue, Guess needs to be moved into a separate non-ancestor module (e.g. a sub-module, or a sibling).
Example:
pub struct Foo(usize);
pub mod x {
pub struct Bar(usize);
impl Bar {
pub fn get(&self) -> usize { self.0 }
}
pub fn make(n: super::Foo) -> Bar {
// can access Foo's fields because this is a
// descendant module, so it is "part of" the
// same module
Bar(n.0)
}
}
pub fn qux(n: x::Bar) -> Foo {
// Can't access Bar's field because it's not exposed to this module
// Foo(n.0)
Foo(n.get())
}

How to return a field from a static structure

I have code:
static mut SETTINGS: Option<Settings> = None;
pub struct Settings {
pub(crate) db_path: String,
pub(crate) is_debug: bool
}
pub fn create_settings(settings: Settings) {
unsafe {
SETTINGS = Option::from(settings)
}
}
pub mod get {
pub fn db_path() -> String {
unsafe {super::SETTINGS.expect("Settings not definition").db_path}
}
}
And I get errors
error[E0507]: cannot move out of static item `SETTINGS`
--> src/settings.rs:16:17
|
16 | unsafe {super::SETTINGS.expect("Settings not definition").db_path}
| ^^^^^^^^^^^^^^^ move occurs because `SETTINGS` has type `std::option::Option<Settings>`, which does not implement the `Copy` trait
I need a static structure and get fields from it. How do I write getter functions so I can just call functions and get settings instead of passing a reference to a struct. Settings are global and alone
You could use once_cell::OnceCell for that (notice that it can be set just once):
use once_cell::sync::OnceCell;
static SETTINGS: OnceCell<Settings> = OnceCell::new();
#[derive(Debug)]
pub struct Settings {
pub(crate) db_path: String,
pub(crate) is_debug: bool
}
pub fn create_settings(settings: Settings) {
SETTINGS.set(settings).expect("Set should occur only once")
}
pub mod get {
pub fn db_path<'a>() -> &'a str {
&super::SETTINGS.get().expect("Settings not definition").db_path
}
}
Playground
Also notice that the return type of db_path changed, it is now &'a str, you can return a reference to the string. If you really want it to return a String then you would have to Clone it.
Most probably you would need also just plain OnceCell, your methods would be just wrapper around it (access and setting).
You can tell the Option that you only want a reference to its contents, rather than taking them. Then you need to clone the value.
pub mod get {
pub fn db_path() -> String {
unsafe {
super::SETTINGS
.as_ref()
.expect("Settings not definition")
.db_path
.clone()
}
}
}

Is it possible to make a private variable in Rust?

I'm trying to generate prime numbers. The code needs to store all the generated primes (to generate the next), to have some private functions to help and one public function (generate_next_prime).
In Java or C++, I would write a PrimesGen class, but in Rust there can't be private variables in a struct. In Python I would probably write a PrimesGen module, but in Rust modules can't have variables.
This code compiles and runs:
struct PrimesGen {
primes_so_far: Vec<i32>,
next_candidate: i32,
}
impl PrimesGen {
pub fn new() -> PrimesGen {
PrimesGen {
primes_so_far: vec![],
next_candidate: 2,
}
}
}
fn main() {
let pg: PrimesGen = PrimesGen::new();
println!("{}", pg.next_candidate);
}
So what do I do?
In Rust, a file is implicitly a module. When you put some code in a foo.rs file, if you want to use this code, you must type mod foo; because the name of this file is implicitly the name of the module. The file with the main is not an exception: it is one module (the base module).
Now, inside a module, everything has access to everything. See this little example to be convinced:
struct Foo {
x: i32, // private
}
struct Bar {}
impl Bar {
fn foo(f: Foo) {
let _ = f.x;
}
}
fn main() {
let f = Foo { x: 42 };
Bar::foo(f);
}
Bar can access the private members of Foo: in Rust, the visibility works by module, and not struct. Inside a same module you cannot do something private towards the same module.
So, if you want to make the variable private in your example, put your struct and implementation inside a module:
mod prime {
pub struct PrimesGen {
primes_so_far: Vec<i32>,
next_candidate: i32,
}
impl PrimesGen {
pub fn new() -> PrimesGen {
PrimesGen {
primes_so_far: vec![],
next_candidate: 2,
}
}
}
}
fn main() {
use prime::*;
let pg: PrimesGen = PrimesGen::new();
println!("{}", pg.next_candidate); // error: field is private
}

Is it possible to create a macro to implement builder pattern methods?

I have a builder pattern implemented for my struct:
pub struct Struct {
pub grand_finals_modifier: bool,
}
impl Struct {
pub fn new() -> Struct {
Struct {
grand_finals_modifier: false,
}
}
pub fn grand_finals_modifier<'a>(&'a mut self, name: bool) -> &'a mut Struct {
self.grand_finals_modifier = grand_finals_modifier;
self
}
}
Is it possible in Rust to make a macro for methods like this to generalize and avoid a lot of duplicating code? Something that we can use as the following:
impl Struct {
builder_field!(hello, bool);
}
After reading the documentation, I've come up with this code:
macro_rules! builder_field {
($field:ident, $field_type:ty) => {
pub fn $field<'a>(&'a mut self,
$field: $field_type) -> &'a mut Self {
self.$field = $field;
self
}
};
}
struct Struct {
pub hello: bool,
}
impl Struct {
builder_field!(hello, bool);
}
fn main() {
let mut s = Struct {
hello: false,
};
s.hello(true);
println!("Struct hello is: {}", s.hello);
}
It does exactly what I need: creates a public builder method with specified name, specified member and type.
To complement the already accepted answer, since it is 4 years old by now, you should check out the crate rust-derive-builder. It uses procedural macros to automatically implement the builder pattern for any struct.

Source trait is inaccessible

The situation is (severely simplified) this (playpen):
mod tokentree {
pub struct TokenTree;
mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
I get the following error (both on nightly and beta):
<anon>:20:22: 20:47 error: source trait is inaccessible
<anon>:20 println!("{:?}", [TokenTree].intern_strs());
^~~~~~~~~~~~~~~~~~~~~~~~~
My problem is that I don't even know what this is supposed to mean.
It needs a pub declaration. Also your declarations are all over the place. Recommended form is to stick your pub mod declarations first, then, use.
Here is the working example.
mod tokentree {
pub struct TokenTree;
pub mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
pub use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
(playpen)
What happened here is that you stumbled upon following glitches:
https://github.com/rust-lang/rust/issues/18241
https://github.com/rust-lang/rust/issues/16264
You can't export your traits from a private module. That's why you need to change mod serialize into pub mod serialize. For example this playpen example demonstrates that exporting struct Export works, but un-commenting the println! will make it stop compiling, because we used a trait.
Tip: One thing that helps me with the visibility rules is to generate doc files and see which doc files are visible.

Resources