Change struct immutable reference

I'm a newbie.
How to change a struct immutable reference field?
I try to clone it then change it, but report error.

Code:

struct A<'a> {
    scores: &'a [u32]
}

fn main () {
    let scores = &[1,2,3];
    let a = A{scores};
    let mut s = a.scores.clone();
    s.sort();
    println!("{:?}", s);
}

Report:

8 |     let mut s = a.scores.clone();
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

error[E0596]: cannot borrow `*s` as mutable, as it is behind a `&` reference
 --> src/bin/main.rs:9:5
  |
8 |     let mut s = a.scores.clone();
  |         ----- help: consider changing this to be a mutable reference: `&mut [u32]`
9 |     s.sort();
  |     ^ `s` is a `&` reference, so the data it refers to cannot be borrowed as mutable

The problem is not changing a reference field.
You are trying to sort a borrowed slice.

yes, I just want to sort an reference array.
In rust , not allow?

You borrowed a slice. Then you have to borrow it mutably to sort it. This violates "shared XOR mutable" rule.

Putting references in structs is a beginner mistake. Almost always you should use owned types in structs.

struct<'a> is an advanced usage for special cases — don't use it until you're proficient with ownership. & it is for creating temporary views into data that is already owned somewhere else, and it can't be used to store or modify any data, except when using interior mutability.

Use:

struct A {
   scores: Vec<u32>,
}

and

let scores = vec![1,2,3];
1 Like

yeah, change to Vec, it worked fine.
Thanks your replay!

If I can't borrow it mutably, there's no way to sort it ?

Yes, there is no way besides using raw pointers, AFAIK.
Why are you trying to do it? :slight_smile:

Nope. If you have a immutable borrow, and the type doesn't contain interior mutability (UnsafeCell type used for Mutex, etc.), then there's no way at all, never ever to mutate anything via that reference.

&[u32] type is absolutely untouchable in all cases in Rust, and there's no way around that, and never will be. You have to use a different type (e.g. copy the data elsewhere)

If you try to hack around it with unsafe code (such as raw pointers or transmute), it will cause Undefined Behavior, and you'll lose all Rust's safety guarantees, and the compiler reserves the right to generate invalid code and cause crashes.

I just do a rust exercism, and met this question :slight_smile:
And I found someone solve it by this way

let mut scores: Vec<u32> = a.scores.to_vec();
scores.sort();

Thanks for your detail description :slight_smile:
I'm a newbie, just hear unsafe little, never use.
Thanks so much!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.