Fixing path::Prefix portability


#1

This, I think, is the biggest portability wart in std. path::Prefix is Windows-specific and cannot be expanded. This has just bitten us because Redox has path prefixes, and they cannot be represented in std today (see my comment on the redox std pr for details).

So I would like to solve this problem, but I’m not sure how. Here are a few ideas:

  • Produce a patch that opens Prefix to expansion with an unstable __NonExhaustive variant and run it through crater to see the fallout. If somebody else produces the patch I’ll do the crater run. I think we should probably do this regardless of any other solution - it’s more correct for this enum to be open.

  • Commandeer an existing variant and document that it is used for multiple purposes. @jackpot51 already produced a patch that does this but it was slightly more intrusive than I expected, and it’s also a slightly distasteful decision to make. One outcome of this decision would be that there is no way to distinguish a Windows-specific path from a Redox-specific path. Personally that does not worry me too much because I contend that Path is not a portable data type, is only meaningful relative to the local system it was produced on.

  • Somehow rework the path internals to store some new side information that is invisible to the current public API; introduce a new API that can access the redox prefix. From just a quick look this seems difficult and would require lots of internal refactoring. Ultimately, this could be equivalent to deprecating the current components API and introducing a components2 API.

  • Use conditional compilation to make new variants appear only on their platforms. There’s not a lot of precedent for this, but one could imagine it might be done with additive scenarios. Maybe some future platforms require the “open Prefix” scenario (handwave).

I do think this is a problem that must be solved somehow. Any opinions about the above, or other bright ideas?

cc @rust-lang/libs @jackpot51


A vision for portability in Rust
#2

Er cc @library_subteam


#3

I strongly believe in the first option - having an open Prefix. The reason is that code which matches prefixes in the case of the second and fourth options would probably have to be inside of #[cfg(windows)] blocks if we overload the Verbatim variant or remove variants from anything that isn’t #[cfg(windows)].

Yes, it might break some crates, but I doubt that Prefix is being used beyond two cases:

// Matching some of, but not all of the prefix variants
match prefix {
   VerbatimUNC(...) => (),
   UNC(...) => (),
  _ => ()
}

or

// Matching one of the prefix variants
if let Verbatim(...) = prefix {
} else {
}

In the cases I have seen, using the path components, prefix is simply thrown away in path processing.


#4

Ideally we’d add __NonExhaustive because nothing would break. In reality I suspect crates will break, so we won’t be able to do that.

In lieu of that I’d be in favor of punting this until we flesh out scenarios more. My guess is that we’re going to need some kind of backcompat story with scenarios and path prefixes may just nicely fall under that, making this issue moot by just gating it behind a scenario (which it arguably should have been in the first place).