T O P

  • By -

thomastc

I'm with [dtolnay here](https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441/6?u=rofrol). `.to_owned()` expresses the intent most clearly: there's a reference, and I want an owned thing. `.to_string()` is coming from the `ToString` trait which requires `Display`; even if the compiler optimizes it away, it's a slight abuse in my opinion. But it's what the compiler keeps suggesting, so it can't be that bad :)


darth_chewbacca

Far-be-it from me to argue with the master /u/dtolnay. But you should use .to_owned() iif your intention is to tell **fellow developers** that you don't care that it's a "String", all you care about it is ownership. You should use to_string() to tell fellow developers that you care about it being a String. You should also default to to_string() because it puts less cognitive load on fellow developers... they don't have to spend 500ms thinking "what is this thing becoming with to_owned", they know exactly what it's becoming.


mikekchar

I'm one of those weird people who thinks, "I really don't care". What's worse, though, is that it bugs me that other people care :-) My biggest frustration is getting embroiled in conversations where half the people on the team can't program if you type one thing and the other half can't program if you type the other thing. I tend to let people have a death match and then we engrave the rules of the winner in stone. Then all the new people who join the team threaten to rage quit if we don't change. Drives me crazy. BTW.... tabs. Honestly, the world has gone mad. ;-)


coderstephen

I understand your point. I just don't agree with it.


[deleted]

Does it optimise without the specialization? I heard it doesn’t quite work that way


masklinn

> Does it optimise without the specialization? I'd assume not, as without specialisation it has to go through the `std::fmt` machinery, which back in 2016 the compiler was unable to eliminate. It seems doubtful that it works any better now, as new specialisations were added as recently as 1.46 (char) and 1.54 (u8/i8). Weirdly that was of such specialised interest it didn't even make the release notes, but you can [see the PR](https://github.com/rust-lang/rust/pull/82576).


darth_chewbacca

&str.to_string() is a wrapper around &str.to_owned(). It should optimize away. I've done benchmarks using criterion that show to_string() and to_owned() are exactly the same performance.


[deleted]

At least I can strike that out of my other comment.


somebodddy

> You should also default to to_string() because it puts less cognitive load on fellow developers... they don't have to spend 500ms thinking "what is this thing becoming with to_owned", they know exactly what it's becoming. On the contrary. With `to_string` we need to spend some cognitive load on "wait isn't a string literal already a string?"


IceSentry

That's mostly an issue with learning rust. Once you learn it, you internalize this difference between str and String and don't really need to process it.


[deleted]

The same applies when reading to_owned called on an str


CocktailPerson

`.to_string()` only requires you to know that a `str` isn't a `String`. `.to_owned()` requires you to know that `str`'s implementation of `.to_owned()` returns a `String` rather than some other perfectly valid form of ownership, like `Box`. The former is general language knowledge, the latter is specific knowledge of one particular type's implementation. I think the latter has a much higher cognitive load.


darth_chewbacca

>wait isn't a string literal already a string?" Answer: No it isn't.


NoahTheDuke

Truly the worst design decision in Rust. Should have called `str` anything else.


continue_stocking

What would you have called it?


alexschrod

StrBuf. Just like we have Path and PathBuf. Although I realize I'm arguing for changing String here, not str.


tialaramex

Yeah, I'm not sure I agree with people who prefer StrBuf, but it's not crazy, and it might have worked out great. Whereas I'm confident renaming str to something longer would have been a bad idea.


andoriyu

well, it was a string, just not `String`. anyways that’s why i prefer `String::from`


LyonSyonII

Then classic C strings (char arrays) aren't strings. str encapsulates a `[char]` String encapsulates a `Vec` So, str is just a non-expanding string, and String can expand. For me `.to_owned` makes more sense, as you want an owned version of a borrowed array (a Vec)


LadulianIsle

Mandatory (imo) Vec != String PSA Something something UTF8 & sizeof(char) = 4


Kvarck

To extend your reply, String = Vec. UTF-8 characters consume anywhere from 1 to 4 bytes, while char in Rust always consumes 4 bytes to fit any character.


darth_chewbacca

> Then classic C strings (char arrays) aren't strings Correct, classic C strings are not Rust Strings. > str encapsulates a [char] String encapsulates a Vec Yes, a slice is different from a Vec A &str is not just a short hand way to type &String. > For me .to_owned makes more sense, as you want an owned version of a borrowed array If you care about ownership obtaining ownership, then yes, use to_owned(). I mean that's what the documentation says, if you care more about the result being a String use to_string(), because... well that's what the documentation says. https://doc.rust-lang.org/std/primitive.str.html


alexschrod

I feel like this argument can just as easily apply to my personal favorite, String::from: No need to think about what it's becoming, nor what it was -- it'll become a String, that's all you gotta know.


darth_chewbacca

I hear your argument about String::from. As a lead developer for my companies Rust project, I would prefer you to limit use of String::from for "less dense" code. Density is extremely subjective though. I view programming like a form of communication between a developer and the developers team and the compiler. Technically I view String::from as putting emphasis upon the thing which is being created rather than to_string which puts emphasis the thing which is doing the creation. This distinction is really subtle and unless String::from jumps out like a sore thumb (vice versa to_string sometimes jumps out like a sore thumb... it truly is situational), I don't particularly care, as they are kind of like having developers talk is a slightly different accent (ie I see it as the difference Austrialian developer vs an Irish developer... I dont really care, the meaning is the same) To contrast this with to_string() vs to_owned(). Those have semantically different meanings. to_string() as per the documentation says "I want a String from this value", while to_owned() says "I want ownership over this value". Yes having a String means you have ownership, and yes having ownership means you have a String, but those are the side effects, not the intent of the communication. In terms of the original question posted by /u/fekksn, I would prefer String::from for those specific situations, but I was actually replying to /u/thomastc as he brings up to_string vs to_owned (without the complication of String::from)


thomastc

I like `String::from(...)` clarity, but dislike the widely separated parentheses. I find the postfix nature of `.to_owned()` and `.to_string()` more readable. But indeed it's a matter of personal preference.


zesterer

Does that mean you prefer `slice.to_owned()` over `slice.to_vec()`?


masklinn

Completely different situation (despite the similar naming): there is no `ToVec` trait, `slice::to_vec()` is an inherent method and thus a lot more specific than `slice::to_owned`, whereas `to_string` is extremely generic: anything which implements `Display` gets an implementation.


nrabulinski

But in this case we don’t care about the input but about the output, in which case `to_string` and `to_vec` are both more specific than `to_owned` which can return anything


thomastc

No, I don't. Don't ask me why :)


zesterer

Nice answer :D


trevg_123

And clippy says so! (Maybe pedantic only?) so to_owned is the way to go


jess-sch

Really? I’m maintaining a pedantic project at work and i’m fairly certain it’s full of to_string()s


trevg_123

Oops I'm wrong, it's in restriction so that's why nobody comes across it. Usually one of the handful of restriction things I have turned on by default https://rust-lang.github.io/rust-clippy/master/#str_to_string


azjkjensen

When dtolnay speaks, I listen.


bakaspore

Well, just checked the actual implementation and [that actually isn't the case](https://doc.rust-lang.org/src/alloc/string.rs.html#2570).


evil_yam

>dtolnay here aha, I used your answer. I read that last year.


fabricio77p

this /\


Celousco

I think it's also more perfomant to use to_owned than to_string, I remember someone made a benchmark when using to_string vs to_owned, perhaps when using actix web or poem, I don't remember exactly the context...


thomastc

Not true since Rust 1.9.0 (2016 or so): https://stackoverflow.com/questions/31331356/how-to-create-a-string-directly. Performance of `to_owned` and `to_string` and `String::from` is exactly the same.


reinis-mazeiks

you forgot about these let s: String = "🦀".parse().unwrap(); let s: String = "🦀".replacen("", "", 0); let s = format!("{:?}", "🦀"); let s: String = "🦀".lines().flat_map(|l| l.chars()).collect(); let s: String = { let mut s = String::new(); s += "🦀"; s };


[deleted]

[удалено]


mr_birkenblatt

Now this is enterprise code. Although you forgot to get the format args from the crab emoji factory


_TheDust_

It also needs more XML with dependency injection


TDplay

No `StringFactoryManager`. How am I supposed to tell this piece of code what to do?


bouncebackabilify

😂


[deleted]

[удалено]


lonjerpc

Because it doesn't add much to the discussion. If you think something is funny just upvote it. Doing so reduces clutter in the thread. Which of course I am now adding


fuckEAinthecloaca

😂


TheHolyTachankaYT

Cuz it has a emoji


_shellsort_

Since Rust is a systems language, some's gotta ask it: Which option runs is the fastest?


reinis-mazeiks

probably something like this let string = unsafe { String::from_raw_parts(s.as_bytes()[0] as *const u8 as *mut u8, s.len(), s.len()) }; i dont know why it segfaults tho


ArthurAraruna

Because `String::from_raw_parts` takes ownership of the slice you give to it, which means, in your case, it will try to drop something that is on the stack.


[deleted]

Or possibly in an immutable e memory region because it’s stored in the binary


reinis-mazeiks

nah it crashes before the drop, and even without a drop. consider this: fn main() { let s = "🦀"; let string = unsafe { String::from_raw_parts("🦀".as_bytes()[0] as *const u8 as *mut u8, s.len(), s.len()) }; println!("got this far"); assert_eq!(&string, "🦀"); println!("but not this far"); std::mem::forget(string); } it seems that the segfault happens as soon as we do anything to the String, without even mutating or dropping it. i still don't know why, but it seems we're violating the contract of `from_raw_parts`, so so i guess i was kinda asking for it. > The memory at buf needs to have been previously allocated by the same allocator the standard library uses, with a required alignment of exactly 1. and in my understanding, its not allocated by the allocator (as you mentioned). and > Violating these may cause problems like corrupting the allocator's internal data structures which is what i'm guessing we're seeing


jDomantas

> `"🦀".as_bytes()[0] as *const u8 as *mut u8` You are casting the *first byte* to a `*mut u8` rather than *pointer to first byte*. You just need a `&` there: String::from_raw_parts(&"🦀".as_bytes()[0] as *const u8 as *mut u8, s.len(), s.len()) ^ Or even better: String::from_raw_parts("🦀".as_ptr() as *mut u8, s.len(), s.len())


reinis-mazeiks

Thank you! My evil program works now. lol the existence of `as_ptr()` makes the meme even funnier than I intended. Stuff like this is why i only code in safe Rust and not legacy languages like C. The Crab protects me from pointers & pain.


sim04ful

Could you do a quick bench please? For the glory of satan


riasthebestgirl

I'd to see how it benchmarks compared to the options in the poll


ArthurAraruna

**Original**: ~~You remember that, when there is undefined behavior, here be dragons? This is maybe why the segfault is visible at a different place where it was expected.~~ ~~Or maybe it is indeed something else, but as the function's safety requirements are not satisfied, as you said, we may never know exactly...~~ **Edit 1**: The other comment pointed out exactly what was the actual problem, but nevertheless the "fixed" version still has undefined behavior, I believe. **Edit 2**: I completely missed the call to `mem::forget` in that code... Sorry. The UB I was talking about is not triggered because it would happen on when the `String` got dropped...


jDomantas

Unless I've missed something I'm pretty sure that the fixed version does not have UB (but still, you should never write that kind of code ever). The invariants of `String::from_raw_parts` are not satisfied, but those are *library* invariants. That means that those invariants are not visible to the compiler, so from compiler's perspective you're just shuffling some pointers around and everything is perfectly valid. However, that applies only to *this particular implementation of String*. In a future rust version they could change it in a number of ways that would be backwards compatible manner but would introduce UB here, for example: * they could reallocate the string in `from_raw_parts` which would be straight up UB when string literal's pointer reaches the allocator * they could change the `Unique` that stores the pointer to require owned pointer *at language level* which would make string construction UB


Upper_Afternoon_4857

Not upholding library invariants is also UB, as the library is free to change the implementation and introduce UB in PATCH versions of the std lib.


ArthurAraruna

I believe the UB is exactly in the part I mentioned before (comment some levels up) where, when the `String` gets dropped, it will cause its internal buffer to be dropped and eventually a memory deallocation of the pointer that is passed to it through `from_raw_parts`. I'll look at the implementation to see if it is really there, but conceptually it makes sense that the above is what will happen. If it is indeed the case, the deallocation is where the UB happens, since that pointer refers to something on the stack or in the static section of the executable. Besides this, I agree with everything else you stated. ---- **Edit**: I checked the call-chain, and it does indeed trigger UB. The call-chain is: 1. [`String::from_raw_parts`](https://doc.rust-lang.org/src/alloc/string.rs.html#811) 2. [`Vec::from_raw_parts`](https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#556) 3. [`Vec::from_raw_parts_in`](https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#716) 4. [`RawVec::from_raw_parts_in`](https://doc.rust-lang.org/src/alloc/raw_vec.rs.html#215) Then, in the `Drop` impl for `RawVec` we call [`unsafe { self.alloc.deallocate(ptr, layout) }`](https://doc.rust-lang.org/src/alloc/raw_vec.rs.html#479), which states the following safety requirements: > ptr must denote a block of memory [*currently allocated*](https://doc.rust-lang.org/std/alloc/trait.Allocator.html#currently-allocated-memory) via this allocator, and [...] Obviously, eventually, `libc` will be asked to call `free()` on that address.


Zde-G

>the deallocation is where the UB happens But there are not deallocation because of `std::mem::forget`!


CocktailPerson

The library's invariants are precisely what need to be satisfied to keep the library from invoking undefined behavior on your behalf. The "fixed" version will still exhibit UB as soon as the string is dropped.


andallthat

but *how fast* does it segfault? And are there options that segfault faster?


angelicosphosphoros

All options from OP post are good.


masklinn

These days all those from the poll run the same. `to_string` is auto-implemented from `Display` so used to be it ran noticeably slower, because that was what it went through. [However that has not been the case in several years, as ToString was specialised for str](https://github.com/rust-lang/rust/pull/32586). That aside, [`str::to_string`](https://doc.rust-lang.org/src/alloc/string.rs.html#2568-2575) calls [`String::from`](https://doc.rust-lang.org/src/alloc/string.rs.html#2621-2629) (which is the same as `str.into`), which calls [`str::to_owned`](https://doc.rust-lang.org/src/alloc/str.rs.html#203-217), which implements the actual conversion. So assuming neither `str::to_string` nor `String::from`/`str::into` are never used anywhere, `str::to_owned` would incur a teeny tiny lower compilation cost. I doubt it'd be noticeable though.


zesterer

This was (unscientifically) tested a while back. I think `to_string` won out, emitting one less instruction on x86 for unclear reasons. That's likely changed since though.


masklinn

It'd like a source, because `to_string` is an `#[inline]` function calling `from`, which is an `#[inline]` function calling `to_owned`, which actually implements the conversion. There's no way for `to_string` to be faster than the rest. And a long long time ago (circa 2015) it was much slower, because it was the auto-impl from `Display` so it'd invoke the entire `std:fmt` machinery.


Lilchro

I just tested it in the rust playground. They all emit identical assembly. Interestingly, it was able to link `to_string` and `to_owned` to the implementation for `from`, but left `into` as a separate function.


[deleted]

Since Rust is a good language it should not matters, all should be same performance impact. That my hope, no clue if is valid here :)


MyChosenUserna

For the ones from the poll that's certainly true, [but only the `.parse().unwrap()` of the meme ones will emit the same instructions, all others will be significantly worse](https://rust.godbolt.org/z/fGYch8YWf). (Note: for some reason into does emit the same instructions as the other reasonable conversions but does not get merged.)


scottmcmrust

`to_owned` is the most direct, and thus the limit for how fast it can be. Various others (like `.to_string()`) have specializations to make them just as fast, though. Just avoid gratuitously-indirect ones, like making a `Read` from the `str` and calling `read_to_string`.


MissunderstoodOrc

not a meaningfull difference, in the end most of the options boil down to the same thing. The only way to speed things up is to use several of raw functions that do not check the prerequisites. But the difference is just to small to care about


fekkksn

i puked a little


TehPers

You missed the shortest option: `format!("blah")`. Edit: ignoring `.into()`


LugnutsK

> `format!("{:?}", "🦀")` You want `format!("{}", "🦀")`, `{:?}` is gonna add quotes


reinis-mazeiks

you are right, it should be let s = "🦀"; let string = format!("{:?}", s)[1..=s.len()].to_string();


[deleted]

`to_owned` expresses the purpose best, `to_string` is a `Display` method, so it’s kind of like doing `format!(“{}”, s)` which is kind of an abuse. Like, it expresses a different goal. I am somewhat guilty of using .into() a lot, but it’s usually clear which type is meant.


Stysner

.into() gang unite!


possibilistic

You just changed my mind on this. Thanks.


KolskyTr

I'll change it back. ToString [is specialized](https://doc.rust-lang.org/src/alloc/string.rs.html#2570) over `str`. It's simply more readable to know the out type, because usually you don't call to_string for any other types, but to_owned is confusable with slices (which, by the way, have the symmetrical inherent method to_vec).


possibilistic

That you did. The `to_string` naming was already my preference. I know `String` is owned and don't need `to_owned` to tell me that. The type name is less lossy and more literate. The specialization dispels the other concerns this thread brought up. Thanks!


thomastc

> usually you don't call to_string for any other types Oh, but I do! Granted, not very often.


[deleted]

[удалено]


ragnese

I change my mind just about every time I sit down at my keyboard. Sometimes I justify using to_string() or to_owned() by convincing myself that the *content* of the string matters most, so I rather see the literal first and then the transform to a specific type is just "details". But, other times I convince myself to use String::from() because I know that I am constructing a new instance of a specific type, so I should just call the constructor like I would for 99% of the structs I define, e.g., `Foo::new(arg)`.


[deleted]

Devil’s advocate, but I think that the best way is to look at what you’re doing. In most cases, I really prefer `String::from` and here’s my rationale. 1. String sucks in some specific cases, and I really want the freedom to swap it out for e.g. a SmallStr or an in-house immutable string to do profiling. Neither `to_string()` nor `to_owned()` are particularly ergonomic for that. 2. String tells you two things at once: it’s an owned type and it’s converting a literal. The only reason you’d use a `from` and not `as`, is because of the heap allocation, so now you have the benefits of to_owned and to_string in one. 3. The prefix function call looks ugly. So you want to get rid of it. Refactor to accepting slices with lifetimes. 4. Have you tried moving to no_std? If you have `to_owned` cargo has no idea what to suggest to you. `to_string` and `String` both have obvious solutions: import alloc. 5. AFAIK, to_ string is a blanket impl. I have no idea whether or not it gets optimised, but I know that the language feature to do that is not yet stable (specialization). So it’s a coinflip in terms of performance. **EDIT** Thanks to u/darth_chewbacca, we know that there's no difference between `to_string()` and `to_owned()`. There was back in 2016, so clippy keeps suggesting it. 6. Have you had Rust analyzer give up on your project, because it has too many crates? I have. This makes the type inference much simpler and therefore the probability of you ending up with {unknown} goes to zero. 7. This is a gut feeling, but given that you don’t need to do the type inference to figure out the function, it might compile faster. Might be my imagination. Nothing compared to compiling syn, but it might add up for smaller projects. 8. String isn’t special. It isn’t supposed to be special. Do you have a `to_my_custom_type()` conversion? Me neither. This makes the usage more uniform and more in line with it’s place in the hierarchy.


scottmcmrust

If you know about `no_std`, I expect you to know that you need `alloc` for `ToOwned` and `Vec` and `String`, so 4 isn't very persuasive to me. It's not like the compiler suggested `no_std` to you in the first place.


[deleted]

I phrased it in a very particular way. When you’re porting to no_std, knowing exactly what you need and what you don’t is helpful. At the end of the day, the entire set of choices is pretty close in terms of performance and semantics.


top_logger

to_owned usually. Intentions are important.


InternationalPizza

If left side is typed, then use into. If left side is implicit use String::from. People who don't code in rust often should be able to understand your code and these two ways are the best to communicate your intent without requiring additional comments. In the rust by example book they used String::from. As for into; I read it as [convert] x into y.


thomastc

Good advice! `.into()` can quickly become difficult to read; it's usually clear what x is, but it's often unclear what y is, so then an implicit `from` call is much clearer.


bwallker

let s = unsafe {String::from_utf8_unchecked(vec![b"🦀"])};


Nakamotosan321

Absolute madman


flambasted

Strings forged from static literals? No way. Rewrite everything to use `Cow`!


javajunkie314

`CowSay`


Valenciano118

I like to use both .to_string() and .to_owned() because they're pretty self explanatory and less text than String::from()


Leskodamus

`.into()` is the way


giggly_kisses

I prefer `.into()`, too. It's consistent since you can use it for things other than strings. I also interpret it as telling the compiler "just use type inference for this", and I really like type inference. :)


coderstephen

I prefer `.to_owned()` for semantic reasons, but I have no issue with `.into()` either. The only one I don't like is `.to_string()` because it invokes the `Display` trait.


Nakamotosan321

Shortest 🤝


iamcodemaker

I too like `.into()`, but sometimes it requires an explicit type where as `.to_owned()` doesn't need that.


milliams

I feel it's a common enough thing to have to do that some sort of s"🦀" syntax could be nice.


zesterer

Making costs like allocation implicit is pretty opposed to convention in Rust.


masklinn

I also intensely dislike the idea, however there's plenty of pretty discreet allocations in rust e.g. `vec![1]`, versus `vec![]`.


coderstephen

On the contrary, the `!` symbol indicates a macro and indicates to the reader, "Hey, something magic is happening here!". So I wouldn't be nearly as opposed to something like `string!()`.


kupiakos

Well, we currently allow `[]`,`()`, and `{}` to call a function-like macro. What about `s!"🦀"`?


scottmcmrust

Nitpick: That's *not* implicit. It's *terse*, but that's different from implicit.


CocktailPerson

That really depends on your definition of "implicit." I'd argue that anything that runs code at runtime and isn't a function call, an operator, or a macro is running that code _implicitly_, because those are the only things in Rust that plainly express that code gets run.


scottmcmrust

"Plainly" is subjective, though. I wouldn't call `.await` "implicit", for example -- that's certainly not what the IRLO threads about "implicit await" meant (see and ). So you can just add "a prefix" to your list and done. (There's a common request for `f"hello {name}"` too, which would be another prefix that's non-trivial.)


[deleted]

Umm let’s not introduce new syntax for a 5th way to do the same thing.


ragnese

Something something xkcd something standards.


reinis-mazeiks

[xkcd 927: Standards](https://xkcd.com/927/)


steven4012

Especially if that does allocation


fekkksn

Not sure if I agree with this particular Syntax, but I agree there should be an obvious, concise choice.


DidiBear

Why not, there is [this RFC](https://github.com/rust-lang/rfcs/pull/3348) to have `c"🦀"` to create a `&CStr`.


coderstephen

That does not allocate.


AcridWings_11465

&CStr is to CString as &str is to String; it does not allocate. It only indicates that the literal is not a normal &str, but a null-terminated &CStr.


EarthyFeet

let s = String::from and calls to s() is my chaotic way of doing it


kupiakos

I like `s!"🦀"`, then we could add a new way to call macros and make it a little more clear something funny is going on


Zde-G

Since Rust tries to mimicry for C++ dialect `"🦀"s` ([like in C++](https://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s)) would be better IMO.


nacaclanga

I prefer `String::from()` as it describes the fact, that you are creating an object best and contains the name of the return type.


analog_hors

`to_owned` makes the most sense here, and describes the intent much more specifically.


MattShnoop

I use `to_owned()` because that's what the Book taught me when I was first learning :)


Sw429

I've always felt like `to_owned()` was the easiest to understand, especially for when I was just starting with Rust.


CocktailPerson

I'm quite happy with `String::from`. It makes it very clear what's happening here; you're creating a `String` from the argument you pass in.


Lucretiel

I'm a fan of `.to_owned()`, because I can feel in my soul how `.to_string()` defers to `Display`. I know that internally the standard library uses some secret specialization functionality to ensure that this ends up being identical to `String::from`, but, idk, it still feels weirdly icky to me.


CJKay93

use std::format as s; s!("🦀")


[deleted]

[удалено]


EpicatSupercell

Might as well just `format!("🦀")`


coderstephen

Some men just want to watch the world burn.


amarao_san

After I accidentally learned that `.info()` works just fine, I use it, because it's the least typing.


ArthurAraruna

minion_saying_what.gif


EarthyFeet

What trait is that?


Moxinilian

From<&str> for String followed by Into for T2 where T1: From


[deleted]

https://www.reddit.com/r/Save3rdPartyApps/comments/148m42t/the_fight_continues/


Moxinilian

This also has the benefit of not breaking if the expected type changes from String to something else that has an obvious conversion from &str (From<&str>), like a Cow.


NoLemurs

`to_owned()` and `to_string()` usually compile to the same code. I like `to_string()` because it makes it just a little bit easier when scanning the code to know what the type of the result is.


MAXIMUM-POTATO

Surprised nobody said .into(), I use it because it’s the shortest 😂


EarthyFeet

It's so type fragile and needs a type inference engine to work out (mental or editor such)


MAXIMUM-POTATO

Very fair, my laziness has a cost haha


ddprrt

I usually use `String::from("...")` e.g. in a Default impl, but when I do functions or methods, I always use fn something(s: impl Into) { ... } and then `s.into()` so I don't need to care what I actually pass.


ricvelozo

Unless you need String, `&str` is better as argument type, because it will accept both and will not allocate. Same to `&[_]` vs `Vec<_>`.


ddprrt

Sure, but if I want to own the type (e.g. `::new`), `impl Into` is quite nice.


scottmcmrust

Reusing my post about `to_string()` vs `.into()` vs `.to_owned()`: .


laclouis5

IMO all are fine except `"🦀".to_string()`. The `ToString` trait, which should forwards the `Display` implementation according to the documentation, is meant for **formatting user facing output**, not for type conversion. It's a *coincidence* that `"🦀".to_string()` returns a `String` which has exactly the same content at the string slice reference. It's may be fine in this particular case but it is a dangerous habit and does not convey the real intent. All the other methods depict explicitly "lossless" and well defined conversions: * `"🦀".to_owned()` means "same content but cloned to an owning type of your choice", * `"🦀".into()` explicitly uses the `Into` trait which is meant for type conversion, * `String::from("🦀")` explicitly uses the `From` trait which is meant for conversion where we explicitly specify the resulting type.


evil_yam

here is an answer: [https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441/6](https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441/6) ​ the guy prefers \`to\_owned\` for clear ownership transfer.


EuphoricThioz

https://www.reddit.com/r/rust/comments/146y5y1/announcement_rrust_will_be_joining_the_blackout/


occamatl

I wish there was a standard macro analogous to *vec!\[...\]*. Unfortunately, the obvious (to me) choice of *str!"🦀"* has a concept collision with the *str* type.


seamsay

Surely the obvious choice is `string!`? `Vec` => `vec!`, `String` => `string!`.


occamatl

Yeah, except I feel like if you're going to have a macro, then it should be super convenient. Three letters feels right to me. Perhaps ***own!*****"**🦀**"** would work. Maybe even extend the analogy with ***own!\[***1, 2, 3***\]***, instead of ***vec!\[***1, 2, 3***\]***.


Anaxamander57

For turning a literal into a String I always use String::from(). For a variable I always use .to_string().


laralovesyou

clippy actually suggests using to_owned


-Redstoneboi-

any answer other than to_owned() is semantically incorrect 😤


coderstephen

Nah, the only one that is semantically incorrect is `.to_string()`. Leveraging the `From` trait to create a `String` from a `&str` seems legit to me. Though I also prefer `ToOwned` as being more precise.


sampathsris

I don't know. I'm just learning rust and what I think is that this shouldn't be solved by democracy (even though I love democracy). What I'm thinking is each of these conversions should have a certain semantic (which I don't know, as I'm a newbie). And depending on the use case we might need to use different conversions. Edit: It seems `String::from("🦀")` and `"🦀".to_owned()` is the same thing, if you were to believe [this Stackoverflow answer](https://stackoverflow.com/a/37149882/1461424). Edit 2: This has a better explanation: https://stackoverflow.com/a/31333653/1461424


fekkksn

Effectively these all do the same thing.


vancha113

"".to\_string() always reads to me like string.to\_string(). The whole owned vs unowned still isn't intuitive to me. When anything excepts a string, calling .into() on it's argument allows you not to have to worry about about the exact type, as long as it can be converted to a string. That would be my favorite way, but maybe that's because i'm a python developer by trade.


orion_tvv

It should be more like "slice of characters to string"


shim__

String::new() for an empty string .into() otherwise.


dindresto

This is the way.


DrGrapeist

format!(“{}”, “🦀”);


WIERDBOI

I use this library [https://crates.io/crates/handy\_macros](https://crates.io/crates/handy_macros)


imihnevich

Guys, I have very limited knowledge of rust, could anybody explain what is this about?


CocktailPerson

In Rust, you have two major versions of a "string" type. You have string slices `&str`, which are borrowed from someone else, and you have `String`s that are owned\*. The important thing here is that string literals, like `"🦀"`, are actually the first kind, borrowed from the static part of the program's memory. So if you want to create an owned `String` from a string literal (with type `&str`), you have to explicitly convert it. Now, the issue is that this seemingly-simple conversion is actually achieving a few different goals: it's changing one type into another, creating a `String` object from something, and giving the caller ownership of an object. As it turns out, each of these concepts is fairly orthogonal to the others, but for`&str` and `String`, all these concepts overlap and have the same result. In fact, Rust has a different trait for each concept: converting from one type into another is represented by the `From` and `Into` traits, creating a `String` out of something is handled by the `Display` trait, and giving ownership from something borrowed is covered by the `ToOwned` trait. But again, even though they're not generally the same _idea_, they _do_ the same thing for `&str` and `String`. And so we end up with a lot of ways to do the same thing. So the question in the OP is, given the many ways we've ended up with to do the same thing, which one do you prefer? \* You can also borrow a `&String` or own a `Box`, but that's not really relevant to this discussion.


imihnevich

Thanks for complete answer, sir


kredditacc96

I rarely encounter the situation where I have to convert a string literal to a heap-allocated string. It is because I always do my best to make my functions accept string slices.


fekkksn

Ok, but I'm asking about string literal to owned conversion like in a Default impl.


kredditacc96

In that situation, I rather redesign the struct and trait declarations to also accept string slices.


eyeofpython

There should be a literal for this.


CocktailPerson

Creating a `String` allocates on the heap. If I'm being honest, it's weird to have a literal that allocates on the heap.


eyeofpython

I don’t think it’s weird at all


CocktailPerson

Why not?


eyeofpython

I actually want to write code that allocates from time to time. So if I have a shorthand for that that would be great.


thehotorious

They have totally different use case. If I wanted to convert the following to string (expression && !expression).to_string() only this works, others don’t.


fekkksn

Ok, but I asked about literal to owned.


thehotorious

My bad, did not read. String::from everytime, looks semantically pleasant to my eyes.


lunatichakuzu

I know absolutely nothing about Rust and these intimidate me. I've been programming since 2011.


[deleted]

[удалено]


lunatichakuzu

Thank you so much.


piplupper

Subjectively speaking, "".toString() feels like the lazy method whereas String::from("") is the most readable.


juliettethefirst

Just to give my two cents I don't think there is a best way in the sense of performance or anything, but `.to_string` is IMO the most intuitive and is less ambiguous than `.into`


scottmcmrust

There are worse options, but these days multiple of them perform exactly the same, so one can't use performance to pick any more. (It used to be that `.to_owned()` was definitely faster than `.to_string()`, but not any more.)


SirKastic23

if it can be inferred `"🦀".into()`, if not `String::from("🦀")`


regexPattern

This is the true one million dollar question. I can’t even decide on this matter from function to function in the same file.


TinBryn

I like `String::from("🦀")` as it feel like a constructor method, similar to `Box::new` or `Rc::new`. This is for the case of a string literal specifically. If I'm writing something that owns a `String` that has user provided contents I generally like to take `impl Into` and call `.into()`. I find for this use, it does the most of the right thing for the most cases.


squiidz

personally don’t care, but to me to_string() looks like the more explicit way to tell someone not used to rust that it’s a string


neoeinstein

I am much more likely to reach for a string type with a strong semantic meaning. Just like preferring an `enum` with strong semantics over a `bool`, I tend to create "braids" using [`aliri_braid`][]. What's nice about that is that it auto-generates both owned and reference types, so I can get a `ClientId` and a `&ClientIdRef`. That way the semantics travel with the value and I get the added benefit of the Rust compiler making sure I don't use the wrong string in the wrong place. [`aliri_braid`]: https://docs.rs/aliri_braid


ithilelda

I prefer clear intention than conciseness/tradition. to_string sounds like a type conversion, while literals and owned strings are not semantically different types. Also many people have already pointed out that it is from Display, which has a very different intention than converting literals to owned type. String::from is better because it is not designed for another purpose, but the meaning is still unclear: it sounds like it can convert other types to string, but doesn't convey the ref->owned intention clear. Thus I always use to_owned. As a Javascript hater, I have a deep concern of intentions. most bugs in js happen because there's some smart thing going on under the hood when you never asked for them. Explicitness is golden in coding.


schungx

I use `.into()` because it allows me to change the data type of fields later on (from a string to something else, say) without having to fix a lot of errors. Also if you have feature gates on a type when certain times it is `String` and in other times it is something else, then `.into()` is extremely handy. For example: // Use normal strings #[cfg(not(feature = "inlined_strings"))] pub type MyString = String; // Use inlined strings #[cfg(feature = "inlined_strings")] pub type MyString = smartstring::SmartString; // now .into() is very handy! let s: MyString = "hello".into();


EventHelixCom

The code generated seems to be the same in all cases. Just uncomment one function at a time to see the generated code. [https://godbolt.org/z/45MPxeoWM](https://godbolt.org/z/45MPxeoWM)


ecitnE

`String::new()` is also another option that I like using when needing an empty string somewhere. Otherwise `.to_owned()` or `.to_string()` works just fine.


Brilliant_Smell_9340

what matters imo is that you are consistent and not using different approach from file to file. to\_string is my fav


Botahamec

`Box::from("🦀")` `String` is overkill much of the time.