# Mut String += format\_args!(…);

**URL:** <https://internals.rust-lang.org/t/mut-string-format-args/19461>\
**Category:** language design\
**Created:** [September 1, 2023, 9:23am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461 "2023-09-01T09:23:27Z")\
**Posts on this page:** 17\
**Page:** 2

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [September 3, 2023, 5:44pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/21 "2023-09-03T17:44:37Z")

</div>

We have `Add<&str> for String` already along with the `AddAssign<&str> for String`, I would expect the same pair here.

---

<div class="post-metadata">

**Author:** ![drewkett](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/drewkett/32/7095_2.png) [@drewkett](https://internals.rust-lang.org/u/drewkett)\
**Post date:** [September 3, 2023, 8:11pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/22 "2023-09-03T20:11:23Z")

</div>

Huh. TIL

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [September 5, 2023, 11:31am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/23 "2023-09-05T11:31:36Z")

</div>

Just my 2c, but I'm not fond of `s += format_args!(...)` (or `s.bikeshed(format_args!(...))` for that matter). It feels a bit too magical, and forces the user to learn about `format_args` which in all other cases is merely an implementation detail. Also, it's a bit too easy to mix up with `s += format!("...")` which has exactly the same sematics, is just less efficient (although I guess a lint would help here).

On the other hand, trying to `write!` to a `String` may not be immediately obvious, but it should be pretty obvious in retrospect and pleasantly orthogonal. It should just be documented better – currently there's nothing in the `String` docs that point to that direction besides the very undiscoverable `Write` impl at the very bottom of the page. At least the docs for `add_assign` and `push_str` could be updated to mention the `write!` idiom. There's also the very recently added Clippy lint `format_push_string` although it's allow by default.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [September 5, 2023, 1:18pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/24 "2023-09-05T13:18:00Z")

</div>

But using the `write!`-trait comes at the inconvenience of an unecessary and unreachable error path. Two potential alternatives:

- It could live as a method on `fmt::Arguments`.

- The `ToString` trait could have a method accepting an existing buffer for append. It's implemented with a _specialization_ for `fmt::Arguments` as-is already, this could then also be sutiable specialized for performance.

- On that note, an appending method on `ToString` would make the usage `Display` potentially more efficient. Since, as `impl<T: Display> ToString for T` puts it:

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [September 5, 2023, 1:23pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/25 "2023-09-05T13:23:27Z")

</div>

> [@197g](#):
>
> But using the `write!`-trait comes at the inconvenience of an unecessary and unreachable error path.

Yeah, I meant (but failed to explicitly state) that some way of resolving the `write!` error situation (even if hackish) would be preferable to the `format_args!` alternative. What about simply an annotation like `allow(unused_result)`?

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [September 5, 2023, 2:04pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/26 "2023-09-05T14:04:27Z")

</div>

Previous discussion here:

> [@Add an easier way to append \`T: Display\` to \`String\` to stdlib?](https://internals.rust-lang.org/t/add-an-easier-way-to-append-t-display-to-string-to-stdlib/10607):
>
> I am regularly annoyed when I need to append new formatted content to an existing buf: &mut String. I think the official way to do this is use std::fmt::Write; write!(buf, "{}", data).unwrap(); The problem with this is: You need to import Write It's hard to remember which Write should be imported there's unwrap that can't actually fire For this reason, I often just do buf += &format!("...") or buf += &data.to\_string(), which is nicer to write, but is horrible semantics-wise. Do other fo…

Since then, I became even more convinced that this is a trivial papercut which is important to fix in stdlib.

I like `+= format_args!()` solution because its a clear improvement with basically no downsides. We should go and do it.

I wouldn't want for us to stick with `buf += format_args!()` as a long-term (10 years from now) solution --- its a clever use of plumbing and a happy coincidence in library design, but it doesn't seem like a sufficiently good first class solution.

Potential long-term alternative is for rust to gain first-class string interpolation syntax, such that we could write

```rust
buf += f"Hello, {name}!"

```

where `f""` desugars into something like `format_args!`.

---

<div class="post-metadata">

**Author:** ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)\
**Post date:** [September 5, 2023, 10:28pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/27 "2023-09-05T22:28:13Z")

</div>

Another thread I created a while ago: [Method to append any `Display` type to a String](https://internals.rust-lang.org/t/method-to-append-any-display-type-to-a-string/17070)

I would really prefer an inherent method over a `+=` impl, because

- it is less magical
- it is more general (it can be generic over `Display`, whereas a blanket `impl<T> AddAssign<T> for String where T: Display` is not possible)

In the previous discussion, there were only two open questions: The name, and whether the method should accept `T` or `&T` (though most people argued for `&T`).

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [September 5, 2023, 11:14pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/28 "2023-09-05T23:14:39Z")

</div>

> [@Aloso](#):
>
> I would really prefer an inherent method over a `+=` imp

I don't see any reason why we shouldn't just do both.

As for the name question, I think `push_display` is the obvious choice. While it's a little clunky, it's also very clear from the name what it happening.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [September 6, 2023, 11:21am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/29 "2023-09-06T11:21:52Z")

</div>

> [@jdahlstrom](#):
>
> It feels a bit too magical, and forces the user to learn about `format_args`

`write!` is quite magical for Rust. It is completely duck-typed — it doesn't use `Write` traits, it takes anything that compiles with `.write_fmt(args)` appended to it. It doesn't even care about the function type or return type. It takes even bogus signatures like `fn write_fmt(&self, f: impl Sized) -> ()`.

Compared to that `format_args!` is pretty tame and well-behaved.

~~If `format_args!` could be made to borrow its arguments for a longer lifetime…~~ [(eh, can't)](https://internals.rust-lang.org/t/format-args-with-long-lifetimes/19494).

---

<div class="post-metadata">

**Author:** ![VitWW](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vitww/32/10822_2.png) [@VitWW](https://internals.rust-lang.org/u/VitWW)\
**Post date:** [September 7, 2023, 11:23pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/30 "2023-09-07T23:23:19Z")

</div>

If a new operator `++` for concatenation strings would be added, then `++=` also could be added

---

<div class="post-metadata">

**Author:** ![samuelpilz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/samuelpilz/32/11225_2.png) [@samuelpilz](https://internals.rust-lang.org/u/samuelpilz)\
**Post date:** [September 8, 2023, 7:43pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/31 "2023-09-08T19:43:36Z")

</div>

`String`s can already be concatenated with `+` and `+=` (with other strings). What would the operator `++` do differently?

The question here is if it a good idea to allow other right-hand-sides (`impl Display` or `fmt::Arguments`) for `+` and `+=`.

---

<div class="post-metadata">

**Author:** ![hyeonu](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hyeonu/32/2162_2.png) [@hyeonu](https://internals.rust-lang.org/u/hyeonu)\
**Post date:** [September 11, 2023, 5:47pm UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/32 "2023-09-11T17:47:18Z")

</div>

As a humble bikeshedding enthusiasist I'm respectfully reminding that `String::write()` is not occupied in any popular way I'm aware of.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [September 17, 2023, 2:47am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/33 "2023-09-17T02:47:31Z")

</div>

Are there other parts of the stdlib that are duck typed like `write!`?

It's very frustrating to work with and doesn't feel likes regular rust code at all.

It would be much better to have a trait to abstract away the two Writes (std::io::Write and std::fmt::Write)

---

<div class="post-metadata">

**Author:** ![veykril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/veykril/32/12847_2.png) [@veykril](https://internals.rust-lang.org/u/veykril)\
**Post date:** [September 20, 2023, 11:08am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/34 "2023-09-20T11:08:32Z")

</div>

There is also an [RFC for postfix macros](https://github.com/rust-lang/rfcs/pull/2442) which would be another way to tackle this possibly, resulting in something like `buffer.write_to!("{x}")`. Not sure if I personally like this though, mainly raising it as another possible option.

---

<div class="post-metadata">

**Author:** ![veykril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/veykril/32/12847_2.png) [@veykril](https://internals.rust-lang.org/u/veykril)\
**Post date:** [September 20, 2023, 11:39am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/35 "2023-09-20T11:39:22Z")

</div>

I just had a look at that, the problem is that using a qualified path we lose out on the autoref behavior of `$buf.write_fmt`

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [September 24, 2023, 6:42am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/36 "2023-09-24T06:42:34Z")

</div>

> [@jdahlstrom](#):
>
> Just my 2c, but I'm not fond of `s += format_args!(...)` (or `s.bikeshed(format_args!(...))` for that matter). It feels a bit too magical, and forces the user to learn about `format_args` which in all other cases is merely an implementation detail.

It's certainly not great, but `format_args!` is definitely already more than an implementation detail, and is already worth learning about for some use-cases. I've written code that calls it directly on multiple occasions when I wanted to avoid the intermediate `String` allocations caused by `format!`. The name is a bit suboptimal (`format_lazy!` or so would better reflect what happens), but oh well.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [December 23, 2023, 6:42am UTC](https://internals.rust-lang.org/t/mut-string-format-args/19461/37 "2023-12-23T06:42:37Z")

</div>

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

[Previous page](https://internals.rust-lang.org/t/mut-string-format-args/19461.md?page=1)
