#How to turn a &self into a &mit self for one time use

8 messages · Page 1 of 1 (latest)

dusk rain
#

I've been working on a compiler and I'm struggling with turning a &self into &mut self. Admittedly I just want to provide a nice error message before exiting from a critical error. So the self can be consumed in the process of making it mutable. I've been trying to use a refcell to create interior mutability but apparently this isn't enough.

This is my where I'd like to handle a potential critical error

fn add_constants(&self, chunk: &mut Chunk) {
        chunk.add_constant(match &self.source[self.previous.get_range()].parse::<Value>() {
            Result::Ok(value) => *value,
            Result::Err(err) => {
                let temp: RefCell<&Parser> = RefCell::new(self);
                error_at_current(&mut temp.borrow_mut(), &err.to_string());
                std::process::exit(3); // this is a critical failure. If this occurs we can infer a deep parsing error in [Scanner::scan_token].
            }
        }, self.previous.line as usize)
    }

This is my error handling at the moment

pub fn error_at_current(parser: &mut Parser, error_message: &str){
   error_at(parser, error_message, parser.current.line as usize);
}

fn error_at(parser: &mut Parser, error_message: &str, line: usize){
   print!("[line {}] Error", line);

   if parser.panic_mode{
       return;
   }
   match parser.current.token_type {
       TokenType::TokenEOF => println!(" at end"),
       TokenType::TokenError => (),
       _ => println!(" at {}", &parser.source[parser.previous.get_range()])
   }
   
   println!("{}", error_message);
   parser.had_error = true;
   parser.panic_mode = true;
}
#

And this is the error message I'm still too unskilled to implement ```rs
error[E0596]: cannot borrow data in dereference of RefMut<'_, &Parser<'_>> as mutable
--> src/backend/parser.rs:55:34
|
55 | error_at_current(&mut temp.borrow_mut(), &err.to_string());
| ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait DerefMut is required to modify through a dereference, but it is not implemented for RefMut<'_, &Parser<'_>>

pulsar bramble
#

You can't do this. If you want to get &mut from &, it needs to always have interior mutability. You can't introduce it only when you need it. It looks like all you're doing is setting some booleans so you could make those AtomicBool.

dusk rain
#

Can you elaborate on that?

#

AtomicBool?

pulsar bramble
pulsar bramble
#

It would look something like this:

fn error_at(parser: &Parser, error_message: &str, line: usize) {
    print!("[line {}] Error", line);

    parser.had_error.store(true, Ordering::Relaxed);
    if parser.panic_mode.swap(true, Ordering::Relaxed) {
        return;
    }

    match parser.current.token_type {
        TokenType::TokenEOF => println!(" at end"),
        TokenType::TokenError => (),
        _ => println!(" at {}", &parser.source[parser.previous.get_range()]),
    }

    println!("{}", error_message);
}
```I'm not sure what semantics `had_error` is supposed to have, so that part may not be correct. It may be more appropriate to have one `AtomicU8` that encodes both. You definitely want to use `swap` for `panic_mode` though, since that ensures you only run the following code one time.
dusk rain
#

Hey, thank you! I really appreciate the help, you know as someone who's new to rust this kind of help is really constructive!