Why value remains borrowed even after its sope ends? - rust

I am trying to break a text intro substrings.
However the Rust compiler issues E0505.
Here is a cut down version of the code:
struct N<'e> {
name: &'e str,
}
struct BigState<'e> {
text: &'e str,
nm: Option<N<'e>>,
}
fn mod_text<'e>(s: &'e mut &'e str) -> N<'e> {
let h = s.split_at(3).0;
*s = s.split_at(3).1;
return N { name: h };
}
fn print_and_destroy(bs: BigState) {
println!("{:}", bs.text);
println!("{:}", bs.nm.unwrap().name);
}
fn main() {
let text = "12345789";
let mut bs = BigState {
text: text,
nm: None,
};
{
let fresh_nm = mod_text(&mut bs.text);
bs.nm = Some(fresh_nm);
}
print_and_destroy(bs);
}
I don't understand why is bs.text still borrowed after the function mod_text returns.
The expected result whould be:
456789
123
What has to give so the code will compile?

Related

Get struct from inside tuple variant [duplicate]

I wish that enums in Rust can be used like Haskell's productive type. I want to
access a field's value directly
assign a field's value directly or make a clone with the changing value.
Directly means that not using too long pattern matching code, but just could access like let a_size = a.size.
In Haskell:
data TypeAB = A {size::Int, name::String} | B {size::Int, switch::Bool} deriving Show
main = do
let a = A 1 "abc"
let b = B 1 True
print (size a) -- could access a field's value directly
print (name a) -- could access a field's value directly
print (switch b) -- could access a field's value directly
let aa = a{size=2} -- could make a clone directly with the changing value
print aa
I tried two styles of Rust enum definition like
Style A:
#[derive(Debug)]
enum EntryType {
A(TypeA),
B(TypeB),
}
#[derive(Debug)]
struct TypeA {
size: u32,
name: String,
}
#[derive(Debug)]
struct TypeB {
size: u32,
switch: bool,
}
fn main() {
let mut ta = TypeA {
size: 3,
name: "TAB".to_string(),
};
println!("{:?}", &ta);
ta.size = 2;
ta.name = "TCD".to_string();
println!("{:?}", &ta);
let mut ea = EntryType::A(TypeA {
size: 1,
name: "abc".to_string(),
});
let mut eb = EntryType::B(TypeB {
size: 1,
switch: true,
});
let vec_ab = vec![&ea, &eb];
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
// Want to do like `ta.size = 2` for ea
// Want to do like `ta.name = "bcd".to_string()` for ea
// Want to do like `tb.switch = false` for eb
// ????
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
}
Style B:
#[derive(Debug)]
enum TypeCD {
TypeC { size: u32, name: String },
TypeD { size: u32, switch: bool },
}
fn main() {
// NOTE: Rust requires representative struct name before each constructor
// TODO: Check constructor name can be duplicated
let mut c = TypeCD::TypeC {
size: 1,
name: "abc".to_string(),
};
let mut d = TypeCD::TypeD {
size: 1,
switch: true,
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
// Can't access a field's value like
// let c_size = c.size
let c_size = c.size; // [ERROR]: No field `size` on `TypeCD`
let c_name = c.name; // [ERROR]: No field `name` on `TypeCD`
let d_switch = d.switch; // [ERROR]: No field `switch` on `TypeCD`
// Can't change a field's value like
// c.size = 2;
// c.name = "cde".to_string();
// d.switch = false;
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
}
I couldn't access/assign values directly in any style. Do I have to implement functions or a trait just to access a field's value? Is there some way of deriving things to help this situation?
What about style C:
#[derive(Debug)]
enum Color {
Green { name: String },
Blue { switch: bool },
}
#[derive(Debug)]
struct Something {
size: u32,
color: Color,
}
fn main() {
let c = Something {
size: 1,
color: Color::Green {
name: "green".to_string(),
},
};
let d = Something {
size: 2,
color: Color::Blue { switch: true },
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
let _ = c.size;
}
If all variant have something in common, why separate them?
Of course, I need to access not common field too.
This would imply that Rust should define what to do when the actual type at runtime doesn't contain the field you required. So, I don't think Rust would add this one day.
You could do it yourself. It will require some lines of code, but that matches the behavior of your Haskell code. However, I don't think this is the best thing to do. Haskell is Haskell, I think you should code in Rust and not try to code Haskell by using Rust. That a general rule, some feature of Rust come directly from Haskell, but what you want here is very odd in my opinion for Rust code.
#[derive(Debug)]
enum Something {
A { size: u32, name: String },
B { size: u32, switch: bool },
}
impl Something {
fn size(&self) -> u32 {
match self {
Something::A { size, .. } => *size,
Something::B { size, .. } => *size,
}
}
fn name(&self) -> &String {
match self {
Something::A { name, .. } => name,
Something::B { .. } => panic!("Something::B doesn't have name field"),
}
}
fn switch(&self) -> bool {
match self {
Something::A { .. } => panic!("Something::A doesn't have switch field"),
Something::B { switch, .. } => *switch,
}
}
fn new_size(&self, size: u32) -> Something {
match self {
Something::A { name, .. } => Something::A {
size,
name: name.clone(),
},
Something::B { switch, .. } => Something::B {
size,
switch: *switch,
},
}
}
// etc...
}
fn main() {
let a = Something::A {
size: 1,
name: "Rust is not haskell".to_string(),
};
println!("{:?}", a.size());
println!("{:?}", a.name());
let b = Something::B {
size: 1,
switch: true,
};
println!("{:?}", b.switch());
let aa = a.new_size(2);
println!("{:?}", aa);
}
I think there is currently no built-in way of accessing size directly on the enum type. Until then, enum_dispatch or a macro-based solution may help you.

Rust proc_macro's: adding constants

I am trying to add a procedural macro that adds constant field to a struct.
Example:
#[add_const]
struct MyStruct {
id: u32,
name: String
}
// Expands to:
struct MyStruct {
id: u32,
name: String
}
impl MyStruct {
const FIELDS: [&'static str; 2] = ["id", "name"];
const TYPES: [syn::Type; 2] = [/*Types of the fields*/];
}
My code for the procedural macro is the following:
#[proc_macro_attribute]
pub fn add_const(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let item_struct = parse_macro_input!(input as ItemStruct);
let struct_name = &item_struct.ident;
let fields: Vec<(String, syn::Type)>;
if let syn::Fields::Named(ref _fields) = item_struct.fields {
let _fields = &_fields.named;
fields = _fields.iter().map(|field| {
if let Some(ident) = &field.ident {
let field_name: String = ident.to_string();
let field_type = &field.ty;
let entry = (field_name, field_type.to_owned());
entry
} else {
panic!("Only named fields are supported.")
}
}).collect();
} else {
panic!("The row struct has no fields.");
}
let mut field_names: Vec<String> = Vec::new();
let mut field_types: Vec<syn::Type> = Vec::new();
fields.iter().for_each(|field| {
let (_name, _type) = field;
field_names.push(_name.to_owned());
field_types.push(_type.to_owned());
});
TokenStream::from(
quote!(
#item_struct
impl #struct_name {
const FIELDS: [&'static str; #field_len] = [#(#field_names),*];
const TYPES: [syn::Type; #field_len] = [#(#field_types),*];
}
)
)
}
This throws the following errors:
error[E0423]: expected value, found builtin type `i32`
--> tests/table_row.rs:7:13
|
7 | id: i32,
| ^^^ not a value
error[E0423]: expected value, found struct `String`
--> tests/table_row.rs:8:15
|
8 | name: String,
| ^^^^^^ help: use struct literal syntax instead: `String { vec: val }`
|
::: /Users/jonaseveraert/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/string.rs:292:1
|
292 | pub struct String {
| ----------------- `String` defined here
I have been able to iron down where the problem lies;
/*CODE*/
impl #struct_name {
const FIELDS: [&'static str; #field_len] = [#(#field_names),*];
// const TYPES: [syn::Type; #field_len] = [#(#field_types),*]; // Commenting out this line makes the errors disappear
}
/*MORE CODE*/
How can I fix this? i.e. how can I add the second constant without the errors appearing and why do those errors appear?
Thank you in advance,
Jonas

Rust tells ''value moved here, in previous iteration of loop"

I'm implementing a parser combinator library:
#[derive(Debug)]
enum Parser {
Char(char),
Positive(Box<Parser>),
}
impl Parser {
fn run(self, s: &str) -> (bool, &str) {
match self {
Parser::Char(ch) => {
if s[0..1].chars().next().unwrap() == ch {
(true, &s[1..])
} else {
(false, s)
}
}
Parser::Positive(parser) => {
//println!("{:?}", parser);
let mut s = s;
let mut res = (false, s);
let parser = *parser;
loop {
let ret = parser.run(s);
if !ret.0 {
break;
}
res = ret;
s = res.1
}
res
}
_ => (false, s),
}
}
}
pub fn run() {
let x = Parser::Positive(Box::new(Parser::Char('a')));
let ret = x.run("aaa");
println!("{} {}", ret.0, ret.1);
}
I'm getting the error
error[E0382]: use of moved value: `parser`
--> src/lib.rs:25:31
|
22 | let parser = *parser;
| ------ move occurs because `parser` has type `Parser`, which does not implement the `Copy` trait
...
25 | let ret = parser.run(s);
| ^^^^^^ value moved here, in previous iteration of loop
I have no idea why this happens. I've tried to add the Copy trait to the Parser enum, but this causes other errors. Why can't I call parser.run() in a loop, or even twice? A single call compiles and runs perfectly.
Would it be better to use a struct instead of an enum?
OK, changed the function's signature to
fn run<'a>(&self, s: &'a str) -> (bool, &'a str)
now and needed some other lines to be fixed.
Works now, but I don't know why.

Polymorphism in Rust and trait references (trait objects?)

I'm writing a process memory scanner with a console prompt interface in Rust.
I need scanner types such as a winapi scanner or a ring0 driver scanner so I'm trying to implement polymorphism.
I have the following construction at this moment:
pub trait Scanner {
fn attach(&mut self, pid: u32) -> bool;
fn detach(&mut self);
}
pub struct WinapiScanner {
pid: u32,
hprocess: HANDLE,
addresses: Vec<usize>
}
impl WinapiScanner {
pub fn new() -> WinapiScanner {
WinapiScanner {
pid: 0,
hprocess: 0 as HANDLE,
addresses: Vec::<usize>::new()
}
}
}
impl Scanner for WinapiScanner {
fn attach(&mut self, pid: u32) -> bool {
let handle = unsafe { OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) };
if handle == 0 as HANDLE {
self.pid = pid;
self.hprocess = handle;
true
} else {
false
}
}
fn detach(&mut self) {
unsafe { CloseHandle(self.hprocess) };
self.pid = 0;
self.hprocess = 0 as HANDLE;
self.addresses.clear();
}
}
In future, I'll have some more scanner types besides WinapiScanner, so, if I understand correctly, I should use a trait reference (&Scanner) to implement polymorphism. I'm trying to create Scanner object like this (note the comments):
enum ScannerType {
Winapi
}
pub fn start() {
let mut scanner: Option<&mut Scanner> = None;
let mut scanner_type = ScannerType::Winapi;
loop {
let line = prompt();
let tokens: Vec<&str> = line.split_whitespace().collect();
match tokens[0] {
// commands
"scanner" => {
if tokens.len() != 2 {
println!("\"scanner\" command takes 1 argument")
} else {
match tokens[1] {
"list" => {
println!("Available scanners: winapi");
},
"winapi" => {
scanner_type = ScannerType::Winapi;
println!("Scanner type set to: winapi");
},
x => {
println!("Unknown scanner type: {}", x);
}
}
}
},
"attach" => {
if tokens.len() > 1 {
match tokens[1].parse::<u32>() {
Ok(pid) => {
scanner = match scanner_type {
// ----------------------
// Problem goes here.
// Object, created by WinapiScanner::new() constructor
// doesn't live long enough to borrow it here
ScannerType::Winapi => Some(&mut WinapiScanner::new())
// ----------------------
}
}
Err(_) => {
println!("Wrong pid");
}
}
}
},
x => println!("Unknown command: {}", x)
}
}
}
fn prompt() -> String {
use std::io::Write;
use std::io::BufRead;
let stdout = io::stdout();
let mut lock = stdout.lock();
let _ = lock.write(">> ".as_bytes());
let _ = lock.flush();
let stdin = io::stdin();
let mut lock = stdin.lock();
let mut buf = String::new();
let _ = lock.read_line(&mut buf);
String::from(buf.trim())
}
It's not a full program; I've pasted important parts only.
What am I doing wrong and how do I implement what I want in Rust?
Trait objects must be used behind a pointer. But references are not the only kind of pointers; Box is also a pointer!
let mut scanner: Option<Box<Scanner>> = None;
scanner = match scanner_type {
ScannerType::Winapi => Some(Box::new(WinapiScanner::new()))
}

Correctly setting lifetimes and mutability expectations in Rust

I'm rather new to Rust and have put together a little experiment that blows my understanding of annotations entirely out of the water. This is compiled with rust-0.13.0-nightly and there's a playpen version of the code here.
The meat of the program is the function 'recognize', which is co-responsible for allocating String instances along with the function 'lex'. I'm sure the code is a bit goofy so, in addition to getting the lifetimes right enough to get this compiling I would also happily accept some guidance on making this idiomatic.
#[deriving(Show)]
enum Token<'a> {
Field(&'a std::string::String),
}
#[deriving(Show)]
struct LexerState<'a> {
character: int,
field: int,
tokens: Vec<Token<'a>>,
str_buf: &'a std::string::String,
}
// The goal with recognize is to:
//
// * gather all A .. z into a temporary string buffer str_buf
// * on ',', move buffer into a Field token
// * store the completely extracted field in LexerState's tokens attribute
//
// I think I'm not understanding how to specify the lifetimes and mutability
// correctly.
fn recognize<'a, 'r>(c: char, ctx: &'r mut LexerState<'a>) -> &'r mut LexerState<'a> {
match c {
'A' ... 'z' => {
ctx.str_buf.push(c);
},
',' => {
ctx.tokens.push(Field(ctx.str_buf));
ctx.field += 1;
ctx.str_buf = &std::string::String::new();
},
_ => ()
};
ctx.character += 1;
ctx
}
fn lex<'a, I, E>(it: &mut I)
-> LexerState<'a> where I: Iterator<Result<char, E>> {
let mut ctx = LexerState { character: 0, field: 0,
tokens: Vec::new(), str_buf: &std::string::String::new() };
for val in *it {
let c:char = val.ok().expect("wtf");
recognize(c, &mut ctx);
}
ctx
}
fn main() {
let tokens = lex(&mut std::io::stdio::stdin().chars());
println!("{}", tokens)
}
In this case, you're constructing new strings rather than borrowing existing strings, so you'd use an owned string directly:
use std::mem;
#[deriving(Show)]
enum Token {
Field(String),
}
#[deriving(Show)]
struct LexerState {
character: int,
field: int,
tokens: Vec<Token>,
str_buf: String,
}
// The goal with recognize is to:
//
// * gather all A .. z into a temporary string buffer str_buf
// * on ',', move buffer into a Field token
// * store the completely extracted field in LexerState's tokens attribute
//
// I think I'm not understanding how to specify the lifetimes and mutability
// correctly.
fn recognize<'a, 'r>(c: char, ctx: &'r mut LexerState) -> &'r mut LexerState {
match c {
'A' ...'z' => { ctx.str_buf.push(c); }
',' => {
ctx.tokens.push(Field(mem::replace(&mut ctx.str_buf,
String::new())));
ctx.field += 1;
}
_ => (),
};
ctx.character += 1;
ctx
}
fn lex<I, E>(it: &mut I) -> LexerState where I: Iterator<Result<char, E>> {
let mut ctx =
LexerState{
character: 0,
field: 0,
tokens: Vec::new(),
str_buf: String::new(),
};
for val in *it {
let c: char = val.ok().expect("wtf");
recognize(c, &mut ctx);
}
ctx
}
fn main() {
let tokens = lex(&mut std::io::stdio::stdin().chars());
println!("{}" , tokens)
}

Resources