Rollup merge of #79809 - Eric-Arellano:split-once, r=matklad

Dogfood `str_split_once()`

Part of https://github.com/rust-lang/rust/issues/74773.

Beyond increased clarity, this fixes some instances of a common confusion with how `splitn(2)` behaves: the first element will always be `Some()`, regardless of the delimiter, and even if the value is empty.

Given this code:

```rust
fn main() {
    let val = "...";
    let mut iter = val.splitn(2, '=');
    println!("Input: {:?}, first: {:?}, second: {:?}", val, iter.next(), iter.next());
}
```

We get:

```
Input: "no_delimiter", first: Some("no_delimiter"), second: None
Input: "k=v", first: Some("k"), second: Some("v")
Input: "=", first: Some(""), second: Some("")
```

Using `str_split_once()` makes more clear what happens when the delimiter is not found.
This commit is contained in:
Tyler Mandry 2020-12-10 21:33:08 -08:00 committed by GitHub
commit 17ec4b8258
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 197 additions and 191 deletions

View file

@ -397,12 +397,9 @@ impl Options {
matches
.opt_strs("default-setting")
.iter()
.map(|s| {
let mut kv = s.splitn(2, '=');
// never panics because `splitn` always returns at least one element
let k = kv.next().unwrap().to_string();
let v = kv.next().unwrap_or("true").to_string();
(k, v)
.map(|s| match s.split_once('=') {
None => (s.clone(), "true".to_string()),
Some((k, v)) => (k.to_string(), v.to_string()),
})
.collect(),
];
@ -707,11 +704,9 @@ fn parse_extern_html_roots(
) -> Result<BTreeMap<String, String>, &'static str> {
let mut externs = BTreeMap::new();
for arg in &matches.opt_strs("extern-html-root-url") {
let mut parts = arg.splitn(2, '=');
let name = parts.next().ok_or("--extern-html-root-url must not be empty")?;
let url = parts.next().ok_or("--extern-html-root-url must be of the form name=url")?;
let (name, url) =
arg.split_once('=').ok_or("--extern-html-root-url must be of the form name=url")?;
externs.insert(name.to_string(), url.to_string());
}
Ok(externs)
}

View file

@ -167,10 +167,8 @@ impl Context {
// `style-suffix.min.css`. Path::extension would just return `css`
// which would result in `style.min-suffix.css` which isn't what we
// want.
let mut iter = filename.splitn(2, '.');
let base = iter.next().unwrap();
let ext = iter.next().unwrap();
let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext,);
let (base, ext) = filename.split_once('.').unwrap();
let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext);
self.dst.join(&filename)
}
}

View file

@ -16,6 +16,7 @@
#![feature(once_cell)]
#![feature(type_ascription)]
#![feature(split_inclusive)]
#![feature(str_split_once)]
#![recursion_limit = "256"]
#[macro_use]

View file

@ -435,8 +435,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// Try looking for methods and associated items.
let mut split = path_str.rsplitn(2, "::");
// this can be an `unwrap()` because we ensure the link is never empty
let (item_str, item_name) = split.next().map(|i| (i, Symbol::intern(i))).unwrap();
// NB: `split`'s first element is always defined, even if the delimiter was not present.
let item_str = split.next().unwrap();
assert!(!item_str.is_empty());
let item_name = Symbol::intern(item_str);
let path_root = split
.next()
.map(|f| f.to_owned())