Could you share the challenge description? Usually it's not necessary to use &str over String, unless you do some optimisation. Also, please pay attention to the pinned thread.
You can put a String inside a struct (and any user-defined type, in fact), it doesn't have to be a &str just because it's in a struct. In fact it's often more advisable to prefer owning types over borrowed types while you are learning the language.
The &str needs a lifetime because it's a borrowed (reference) type, and when it's part of another type, the compiler needs some annotation as to how long you want the referred-to string slice to live at least. That is, a struct may be constructed, used, and destroyed in any number of ways, and the compiler can't infer the underlying lifetime based on the type definition alone.
In contrast when you actually use a &str in executable code (ie. a function), its lifetime will be inferred more often than not based on the way you use it.
// structs1.rs
// Address all the TODOs to make the tests pass!
// I AM NOT DONE
struct ColorClassicStruct<'a> {
name: &'a str ,
hex: &'a str
}
struct ColorTupleStruct<'a> (& 'a str,& 'a str);
#[derive(Debug)]
struct UnitStruct;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classic_c_structs() {
// TODO: Instantiate a classic c struct!
let green = ColorClassicStruct{name: "green", hex:"#00FF00"};
assert_eq!(green.name, "green");
assert_eq!(green.hex, "#00FF00");
}
#[test]
fn tuple_structs() {
// TODO: Instantiate a tuple struct!
let green = ColorTupleStruct("green", "#00FF00");
assert_eq!(green.0, "green");
assert_eq!(green.1, "#00FF00");
}
#[test]
fn unit_structs() {
// TODO: Instantiate a unit struct!
let unit_struct = UnitStruct;
let message = format!("{:?}s are fun!", unit_struct);
assert_eq!(message, "UnitStructs are fun!");
}
}
In this case you need &str b/c that's what tests are calling for. And b/c you have to use &str you have to supply lifetime annotation. If you want to use String in the structs, you need to append .to_string() to all the strs in the tests.
String literals, for example "green", have the type &'static str in Rust.
'static means that the reference is valid for the rest of the program. This is the case for a string literal because it is a reference to data within the binary that will never change or move.
You should not use temporary borrows in structs, because that makes the whole struct temporary and bound to a scope of its content. It will cause you a lot of pain with the borrow checker.
FYI, if you do not intend to edit the string in the struct, Box<str> conveys this intention better than String. String is a string buffer, i.e. it has a length, as well as a capacity.