Разобрав ваш пример до минимума:
struct A {
string_ref: Option<NonNull<String>>,
}
impl A {
fn give_me_string(&self) -> String {
unsafe {
*self.string_ref.unwrap().as_ref()
}
}
}
Здесь есть несколько ошибок:
- Наиболее очевидным является то, что вы пытаетесь стать владельцем
self.string_ref
, даже если вы заимствовали только self
.
. Чтобы решить эту проблему, вы должны использовать оператор match
, который позволяет вам деструктурировать self.string_ref
и не использовать его:
fn give_me_string(&self) -> String {
unsafe {
match self.string_ref {
Some(x) => x.as_ref(),
None => panic!("Had no `string_ref`!")
}
}
}
as_ref
возвращает
&T
, поэтому вы не можете вернуть принадлежащую строку, вместо этого вам нужно либо клонировать ее и
затем вернуть принадлежащую строку, либо взять ссылкук нему:
//Option one: Clone contents
match self.string_ref {
Some(ref x) => x.as_ref().clone(),
_ => //...
}
//Option two: Return reference.
fn give_me_string(&self) -> &str {
unsafe {
match &self.string_ref {
Some(x) => x.as_ref() as _,
_ => //...
}
}
}
Чтобы решить еще одну проблему, упомянутую в комментариях, в вашей функции main
есть следующее утверждение:
string_ref: NonNull::new(&mut String::from("hello world") as *mut String)
Это приведет к UB
из-за своей природы.Вы формируете String
с помощью String::from
, но нигде не храните его значение и вместо этого сразу же приводите его в указатель.Это освободит String
в конце строки, что приведет к UB
.