Pre-RFC: Rename Path and PathBuf


#1

I’d like to propose a naming change to the Rust standard library: rename Path to PathStr and PathBuf to PathString. To explain, let’s look at this table:

Guarantees “Slice” Variety “Owned” Variety
UTF-8 str String
C-compatible CStr CString
OS-compatible OsStr OsString
System path Path PathBuf

As you can see, the Str/String split is consistent, except for the two path types: Path and PathBuf. Obviously, backwards compatibility concerns mean that the current names can’t be eliminated. But they can be deprecated, in favor of PathStr and PathString. The way of doing it would likely be to rename the types, and then provide the old names as aliases.

This is a nit, but fixing it seems like something that would make Rust’s string types more consistent, and approachable for newer Rust programmers.

Thoughts?


#2

This would be a massively impactful deprecation on the ecosystem. Is it worth that amount of churn to fix a nit?


#3

And if it is worth it, wouldn’t people prefer to go the other way?

Guarantees “Slice” Variety “Owned” Variety
UTF-8 str StrBuf
C-compatible CStr CStrBuf
OS-compatible OsStr OsStrBuf
System path Path PathBuf

:duck:


#4

I don’t see why paths would be considered a string type. Paths have different semantics than strings. If it’s just because they have a string constructor, there are many other types that also have string constructors.


#5

I agree with @quodlibetor—paths are the types that get the names right. If I could go back in time and change things, I’d change str to String and String to StringBuf. I understand that in the earlier days of Rust there was a long debate about what to call them and that str/String were preferred for some reason, but I think it’d be way easier to teach the difference between the two types if they had names that better represent what they are. Paths are unusual in that they actually are named that way!


#6

I’d like to strongly echo @sfackler’s thoughts. This would be a massive change. I personally think there should be a very high standard of evidence required for a change like this, although I’m not sure how to collect said evidence. We could at least start with: what are we hoping to gain by this change?

I also somewhat subscribe to the philosophy that Rust will have warts like these that we just need to live with.


#7

This would be a massive change.

What if just leave deprecated type Path = PathStr; type PathBuf = PathString; for compatibility?


#8

People migrating past the deprecation warning is the massive change.


#9

Alright, it seems opposition to this is multifaceted and strong. I do not feel particularly strongly about this idea, so for now it seems best not to spend time on it. Thanks everyone!


#10

Is there some centralized-ish list of “things we all kind of agree we’d change if we could go back in time, but won’t because Stability Is A Feature”? Off the top of my head:

  • string names (this thread)
  • lifetime elision for things other than references (mentioned by the ergonomics initiative)
  • no dedicated syntax for dynamic dispatch

Though maybe those last two are both slated to get fixed? Anyway, my main question is whether anyone keeps a list :slight_smile:


#11

There is the rust-2-breakage-wishlist issues tag: https://github.com/rust-lang/rust/issues?q=is%3Aissue+label%3Arust-2-breakage-wishlist+is%3Aclosed


#12

I would really prefer the …Buf approach. Paths have really different semantics. You can check if a path exists, you can add segments, you can check extensions, file stems… Does not make sense in my mind to call it a “string” since it’s much more than that. The others are all strings, and they just differ in the compatibility.


#13
Guarantees “Slice” Variety “Owned” Variety
UTF-8 str StrBuf
C-compatible CStr CStrBuf
OS-compatible OsStr OsStrBuf
System path Path PathBuf

This is one of my big regrets about how 1.0 turned out, and I’d much prefer what you propose. I think such a scheme would go some distance to mitigate the concern that “Rust’s string types are really complicated”.

I wonder how feasible it would be to “change” this by essentially making String an alias for StrBuf, providing a rustfix that makes the adjustment, and leaving it at that for some time – i.e., not deprecating near-term. That would allow the newer name to percolate through the ecosystem without waves of warnings, etc. And people are going to be running rustfix to move to the next epoch anyway. At some distant point in the future, we could eventually deprecate the original name.

cc @nikomatsakis, @withoutboats


#14

If the change is being considered, this is certainly the naming scheme I would prefer. I suggested the smaller change initially because I figured there’d be a desire to minimize the scope of the change. But hey, the path of non deprecating and using rustfix to move people over seems pretty appealing, and then you don’t have to worry about the size of the change as much.


#15

I too prefer this naming scheme. I worry mildly about the “deprecation” of existing documentation and so forth, but a soft deprecation scheme helps here.


#16

I don’t know how feasible the change is, even without deprecation, but it would also be a nice opportunity to finally move str from the language to libcore and rename it to Str.


#17

Maybe I’m just used to current names but I think this would be more confusing.

  • IMO String et al are more accessible names than StrBuf et al. I know a part of the idea is to “make it clearer” than String has a backing vector, but I don’t think putting Buf in the name makes things any clearer in the same way that non-elided lifetimes don’t make things clearer for new users.
  • The mixed documentation would cause a significant amount of confusion, enough that I think it overwhelms the difference between which of these is better.

Maybe I’m just missing the argument.


#18

I think there’s a lot to be said just for the name String. It’s the first thing anyone is going to reach for, and while that does tend to throw them head-first into the &str/String distinction, that’s also a very good motivation for ownership, and not something that would be solved by renaming String anyway.

Keeping the name String around and yet trying to get everyone to use StrBuf will introduce needless confusion on top of this. (“what’s the difference between String and StrBuf? it’s not like Java String/StringBuilder? what’s this third type &str?”) And since we can’t actually remove String without an absolutely earth-shaking epoch, that confusion would likely remain forever.

I don’t think the benefits really outweigh the drawbacks here.


#19

FWIW I (working with mostly mid- to senior- mostly-java engineers) pretty much always explain String with a sentence that is almost exactly “String is StringBuffer, and str is String”. When working with Python or JS folks the explanation is significantly more wordy, but it always includes something like “internal buffer vs is immutable”.

In emphasizing the internal properties of the types it de-emphasizes the owningness of them. The fact that you can return a String/StrBuf from the function that you created it in is at least as important of a property as the fact that it is growable.

I continue to think that StrBuf is easier to teach – as another example, the way that operators work makes more sense in the context of items that have buffers.

I’m glad that I’m not responsible for making any decisions that have to do with whether that benefit outweighs ecosystem doc-churn.


#20

I continue to think that the change does not outweigh the churn this will cause. Imagine new Rust programmers learning about String/str from the book, and then going and seeing StrBuf/str in actual code everywhere that has gone through rustfix. If the String/str naming is already proving difficult to grasp, then changing the name will only make it harder. I concede that “harder” is temporary, but I feel like the length of time is “until the second edition of the book” comes out, which feels like a really long time to me.

I think this is something we should just live with.