Convert format!() from String to &'static str [duplicate] - string

This question already has answers here:
How to convert a String into a &'static str
(4 answers)
Return local String as a slice (&str)
(7 answers)
Is it possible to return either a borrowed or owned type in Rust?
(1 answer)
Closed 5 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I'm stumped on how to interpolate a number and return it in the correct format. I started with the function returning String but then the compiler wanted &'static str. I've read about to_owned but it's not clicking in my head yet. What is the "right" way to do what I'm attempting?
fn ordinal_name(num: i32) -> &'static str {
if num == 1 {
"1st"
} else if num == 2 {
"2nd"
} else if num == 3 {
"3rd"
} else {
format!("{}th", num)
}
}
fn main() {
println!("{}", ordinal_name(5));
}
error[E0308]: mismatched types
--> src/main.rs:9:9
|
1 | fn ordinal_name(num: i32) -> &'static str {
| ------------ expected `&'static str` because of return type
...
9 | format!("{}th", num)
| ^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `std::string::String`
|
= note: expected type `&'static str`
found type `std::string::String`
= note: this error originates in a macro outside of the current crate
This is not a duplicate of String to &'static str - I'm trying to figure how to interpolate an integer with a string and then return a &static str.

Related

Rust newbie question about string replacement [duplicate]

This question already has answers here:
Return local String as a slice (&str)
(7 answers)
Missing Lifetime Operator
(3 answers)
Closed 8 months ago.
fn get_filename_from_url(url: &str, extension: &str) -> str {
let dt = chrono::Local::now();
let cleaned_url = url
.replace("https://", "")
.replace("/", "-")
.replace("?", "-")
.as_str();
return format!(
"{}{}_{}{}",
OUTPUT_FOLDER,
cleaned_url,
dt.format("%Y-%m-%d_%H.%M.%S"),
extension
)
.as_str();
}
I get errors such as:
error[E0106]: missing lifetime specifier
--> src/scraper.rs:14:57
|
14 | fn get_filename_from_url(url: &str, extension: &str) -> &str {
| ---- ---- ^ expected named lifetime parameter
What am I doing wrong?
P.S. I was also interested to see Is there a safe / sanitised filename function in Rust but didn't see a helpful example.

Rust doesn't have a size known at compile-time [duplicate]

This question already has answers here:
What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?
(1 answer)
Return local String as a slice (&str)
(7 answers)
Proper way to return a new string in Rust
(2 answers)
Closed 3 years ago.
I am having problems in an exercise where I try to get an impl block to return the value of the i32 in the struct in str format. I don't know if it is doing well or if it is possible to do this, this is the complete error:
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:6:20
|
6 | fn x(&self) -> str {
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
--> src/main.rs:9:9
|
6 | fn x(&self) -> str {
| --- expected `str` because of return type
...
9 | *_newword
| ^^^^^^^^^ expected `str`, found struct `std::string::String`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:17:5
|
17 | println!("x is: {}", f.x());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
This is the code that I am trying to make work:
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn x(&self) -> str {
let word = *self.x;
let _newword = &word.to_string();
*_newword
}
}
fn main() {
let y = &5;
let f = Foo { x: y };
println!("x is: {}", f.x());
}

Struct str attribute must be reference? [duplicate]

This question already has answers here:
How to solve "returns a value referencing data owned by the current function" error in Rust? [duplicate]
(1 answer)
Return local String as a slice (&str)
(7 answers)
Why can't I return an &str value generated from a String?
(1 answer)
Is there any way to return a reference to a variable created in a function?
(5 answers)
Closed 3 years ago.
For the following code:
fn get_lines() -> String {
String::from("Hello\nWorld")
}
fn get_first_line(s: &String) -> &str {
s.lines().next().unwrap()
}
struct World<'a> {
a_str: &'a str,
}
fn work<'a>() -> World<'a> {
let s1 = get_lines();
let s2 = get_first_line(&s1);
World { a_str: s2 }
}
fn main() {
let w = work();
}
I got the following error:
error[E0515]: cannot return value referencing local variable `s1`
--> src/main.rs:17:5
|
15 | let s2 = get_first_line(&s1);
| --- `s1` is borrowed here
16 |
17 | World { a_str: s2 }
| ^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
How to build a struct instance using s2? Is it a conceptual error of the World struct?
World refers to a str slice which must be owned by something else. Your function work allocates a new String (through get_lines), and makes a reference into it (through get_first_line). When it returns, the String goes out of scope and will be dropped, so you cannot keep a reference to it, since the thing it refers to is no longer there.
If you want a World object that does not depend on a String owned by something else, it will need to own the data itself: Contain a String instead of a &'a str.
See also 'dangling references' in the Rust Book.

str::contains works with references but not with the actual value [duplicate]

This question already has answers here:
The trait `FnMut<(char,)>` is not implemented for `String` when trying to split a string
(2 answers)
str::contains doesn't work when the supplied input is a string reference [duplicate]
(1 answer)
Closed 3 years ago.
Consider a function that searches for a pattern in a huge string of lines and returns the lines on which matches are found:
fn search_insensitive<'a>(query: &str, content: &'a str) -> Vec<&'a str> {
let lowercase_query = query.to_lowercase();
let mut matches: Vec<&str> = Vec::new();
for line in content.lines() {
let lowercase_line = line.to_lowercase();
if lowercase_line.contains(&lowercase_query) {
matches.push(line)
}
}
matches
}
The question I have is around the line if lowercase_line.contains(&lowercase_query). Why is lowercase_query passed as a reference here? If I pass it as a value instead I get the error:
error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String`
--> src/lib.rs:6:27
|
6 | if lowercase_line.contains(lowercase_query) {
| ^^^^^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String`
|
= help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`
= note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`
I checked the definition of the contains function:
pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
pat.is_contained_in(self)
}
I don't see anywhere the need for contains to take a reference. Can someone explain this?
Because Pattern is implemented for &'a String but not for String
impl<'a, 'b> Pattern<'a> for &'b String
But I still don't get the relation between the error message when I do pass it by value
Answered by Jmb
If you look at the docs for Pattern you will see that the last documented impl is for FnMut (char) -> bool, which might explain why the compiler chose to show that specific type. It would probably have been better if the compiler had said impl Pattern<'_>

Variable lifetime qs in function [duplicate]

This question already has answers here:
Return local String as a slice (&str)
(7 answers)
Proper way to return a new string in Rust
(2 answers)
Why can I return a reference to a local literal but not a variable?
(1 answer)
Closed 4 years ago.
fn get_str1<'a>() -> &'a str {
let x = "hello";
return x;
}
fn get_str2<'a>(str1: &str) -> &'a str {
let x: &'a str = (str1.to_string() + "123").as_str();
return x;
}
fn get_str3<'a>(str1: &str) -> &'a str {
let tmp = str1.to_string() + "123";
let x: &'a str = tmp.as_str();
return x;
}
#[test]
fn lifetime_test() {
println!("{}", get_str1());
println!("{}", get_str2("hello"));
println!("{}", get_str3("hello"))
}
When I call get_str1, it has no problem, but when I call get_str2, it has a compilation error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:7:22
|
7 | let x: &'a str = (str1.to_string() + "123").as_str();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 6:1...
--> src/main.rs:6:1
|
6 | fn get_str2<'a>(str1: &str) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: consider using a `let` binding to increase its lifetime
When I call get_str3, it also has a compilation error:
error[E0597]: `tmp` does not live long enough
--> src/main.rs:13:22
|
13 | let x: &'a str = tmp.as_str();
| ^^^ borrowed value does not live long enough
14 | return x;
15 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 11:1...
--> src/main.rs:11:1
|
11 | fn get_str3<'a>(str1: &str) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why do I get these errors and how do I fix get_str2 and get_str3?
The first function works because the string has the 'static lifetime and will be promoted by the compiler.
As for the others..
fn get_str2<'a>(str1: &str) -> &'a str {
let x = (str1.to_string() + "123").as_str();
return x
}
This part: str1.to_string(), isn't returning a string slice... but a new instance of a String. This is basically the same as this:
let x = str1.to_string(); // this is of type String, and its lifetime is local to this function
let y = str1 + "123"; // This consumes str1 and appends a &str to it - thus the lifetime is still of the new String instance above
let z = y.as_str(); // This returns a reference to the local String instance
Reading each comment above, it becomes clear that you're actually trying to return a reference to a local String. You can't do this, because the String will be destroyed at the end of the function and the reference will be invalid.
This applies to your third function as well. You're returning a reference to a String instance that will be destroyed at the end of the function.

Resources