Skip to content

Commit 5aa0239

Browse files
committed
Auto merge of rust-lang#92216 - matthiaskrgr:rollup-luplvuc, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#88858 (Allow reverse iteration of lowercase'd/uppercase'd chars) - rust-lang#91544 (Fix duplicate derive clone suggestion) - rust-lang#92026 (Add some JSDoc comments to rustdoc JS) - rust-lang#92117 (kmc-solid: Add `std::sys::solid::fs::File::read_buf`) - rust-lang#92139 (Change Backtrace::enabled atomic from SeqCst to Relaxed) - rust-lang#92146 (Don't emit shared files when scraping examples from dependencies in Rustdoc) - rust-lang#92208 (Quote bat script command line) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents e983092 + 3afed8f commit 5aa0239

File tree

18 files changed

+418
-57
lines changed

18 files changed

+418
-57
lines changed

Diff for: compiler/rustc_typeck/src/check/method/suggest.rs

+17-16
Original file line numberDiff line numberDiff line change
@@ -1195,11 +1195,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11951195
fn suggest_derive(
11961196
&self,
11971197
err: &mut DiagnosticBuilder<'_>,
1198-
unsatisfied_predicates: &Vec<(
1198+
unsatisfied_predicates: &[(
11991199
ty::Predicate<'tcx>,
12001200
Option<ty::Predicate<'tcx>>,
12011201
Option<ObligationCause<'tcx>>,
1202-
)>,
1202+
)],
12031203
) {
12041204
let mut derives = Vec::<(String, Span, String)>::new();
12051205
let mut traits = Vec::<Span>::new();
@@ -1236,23 +1236,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12361236
traits.push(self.tcx.def_span(trait_pred.def_id()));
12371237
}
12381238
}
1239-
derives.sort();
1240-
let derives_grouped = derives.into_iter().fold(
1241-
Vec::<(String, Span, String)>::new(),
1242-
|mut acc, (self_name, self_span, trait_name)| {
1243-
if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
1244-
if acc_self_name == &self_name {
1245-
traits.push_str(format!(", {}", trait_name).as_str());
1246-
return acc;
1247-
}
1248-
}
1249-
acc.push((self_name, self_span, trait_name));
1250-
acc
1251-
},
1252-
);
12531239
traits.sort();
12541240
traits.dedup();
12551241

1242+
derives.sort();
1243+
derives.dedup();
1244+
1245+
let mut derives_grouped = Vec::<(String, Span, String)>::new();
1246+
for (self_name, self_span, trait_name) in derives.into_iter() {
1247+
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1248+
{
1249+
if last_self_name == &self_name {
1250+
last_trait_names.push_str(format!(", {}", trait_name).as_str());
1251+
continue;
1252+
}
1253+
}
1254+
derives_grouped.push((self_name, self_span, trait_name));
1255+
}
1256+
12561257
let len = traits.len();
12571258
if len > 0 {
12581259
let span: MultiSpan = traits.into();

Diff for: library/alloc/tests/str.rs

+31
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,37 @@ fn test_rev_iterator() {
11831183
assert_eq!(pos, v.len());
11841184
}
11851185

1186+
#[test]
1187+
fn test_to_lowercase_rev_iterator() {
1188+
let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ";
1189+
let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a'];
1190+
1191+
let mut pos = 0;
1192+
let it = s.chars().flat_map(|c| c.to_lowercase()).rev();
1193+
1194+
for c in it {
1195+
assert_eq!(c, v[pos]);
1196+
pos += 1;
1197+
}
1198+
assert_eq!(pos, v.len());
1199+
}
1200+
1201+
#[test]
1202+
fn test_to_uppercase_rev_iterator() {
1203+
let s = "aößü💩στιγμαςDžfiᾀ";
1204+
let v =
1205+
['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A'];
1206+
1207+
let mut pos = 0;
1208+
let it = s.chars().flat_map(|c| c.to_uppercase()).rev();
1209+
1210+
for c in it {
1211+
assert_eq!(c, v[pos]);
1212+
pos += 1;
1213+
}
1214+
assert_eq!(pos, v.len());
1215+
}
1216+
11861217
#[test]
11871218
#[cfg_attr(miri, ignore)] // Miri is too slow
11881219
fn test_chars_decoding() {

Diff for: library/core/src/char/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,13 @@ impl Iterator for ToLowercase {
393393
}
394394
}
395395

396+
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
397+
impl DoubleEndedIterator for ToLowercase {
398+
fn next_back(&mut self) -> Option<char> {
399+
self.0.next_back()
400+
}
401+
}
402+
396403
#[stable(feature = "fused", since = "1.26.0")]
397404
impl FusedIterator for ToLowercase {}
398405

@@ -420,6 +427,13 @@ impl Iterator for ToUppercase {
420427
}
421428
}
422429

430+
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
431+
impl DoubleEndedIterator for ToUppercase {
432+
fn next_back(&mut self) -> Option<char> {
433+
self.0.next_back()
434+
}
435+
}
436+
423437
#[stable(feature = "fused", since = "1.26.0")]
424438
impl FusedIterator for ToUppercase {}
425439

@@ -479,6 +493,26 @@ impl Iterator for CaseMappingIter {
479493
}
480494
}
481495

496+
impl DoubleEndedIterator for CaseMappingIter {
497+
fn next_back(&mut self) -> Option<char> {
498+
match *self {
499+
CaseMappingIter::Three(a, b, c) => {
500+
*self = CaseMappingIter::Two(a, b);
501+
Some(c)
502+
}
503+
CaseMappingIter::Two(b, c) => {
504+
*self = CaseMappingIter::One(b);
505+
Some(c)
506+
}
507+
CaseMappingIter::One(c) => {
508+
*self = CaseMappingIter::Zero;
509+
Some(c)
510+
}
511+
CaseMappingIter::Zero => None,
512+
}
513+
}
514+
}
515+
482516
impl fmt::Display for CaseMappingIter {
483517
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484518
match *self {

Diff for: library/core/tests/char.rs

+6
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ fn test_to_lowercase() {
103103
let iter: String = c.to_lowercase().collect();
104104
let disp: String = c.to_lowercase().to_string();
105105
assert_eq!(iter, disp);
106+
let iter_rev: String = c.to_lowercase().rev().collect();
107+
let disp_rev: String = disp.chars().rev().collect();
108+
assert_eq!(iter_rev, disp_rev);
106109
iter
107110
}
108111
assert_eq!(lower('A'), "a");
@@ -130,6 +133,9 @@ fn test_to_uppercase() {
130133
let iter: String = c.to_uppercase().collect();
131134
let disp: String = c.to_uppercase().to_string();
132135
assert_eq!(iter, disp);
136+
let iter_rev: String = c.to_uppercase().rev().collect();
137+
let disp_rev: String = disp.chars().rev().collect();
138+
assert_eq!(iter_rev, disp_rev);
133139
iter
134140
}
135141
assert_eq!(upper('a'), "A");

Diff for: library/std/src/backtrace.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ use crate::cell::UnsafeCell;
9999
use crate::env;
100100
use crate::ffi::c_void;
101101
use crate::fmt;
102-
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
102+
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
103103
use crate::sync::Once;
104104
use crate::sys_common::backtrace::{lock, output_filename};
105105
use crate::vec::Vec;
@@ -256,7 +256,7 @@ impl Backtrace {
256256
// backtrace captures speedy, because otherwise reading environment
257257
// variables every time can be somewhat slow.
258258
static ENABLED: AtomicUsize = AtomicUsize::new(0);
259-
match ENABLED.load(SeqCst) {
259+
match ENABLED.load(Relaxed) {
260260
0 => {}
261261
1 => return false,
262262
_ => return true,
@@ -268,7 +268,7 @@ impl Backtrace {
268268
Err(_) => false,
269269
},
270270
};
271-
ENABLED.store(enabled as usize + 1, SeqCst);
271+
ENABLED.store(enabled as usize + 1, Relaxed);
272272
enabled
273273
}
274274

Diff for: library/std/src/process/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,22 @@ fn env_empty() {
420420
let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
421421
assert!(p.is_ok());
422422
}
423+
424+
// See issue #91991
425+
#[test]
426+
#[cfg(windows)]
427+
fn run_bat_script() {
428+
let tempdir = crate::sys_common::io::test::tmpdir();
429+
let script_path = tempdir.join("hello.cmd");
430+
431+
crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap();
432+
let output = Command::new(&script_path)
433+
.arg("fellow Rustaceans")
434+
.stdout(crate::process::Stdio::piped())
435+
.spawn()
436+
.unwrap()
437+
.wait_with_output()
438+
.unwrap();
439+
assert!(output.status.success());
440+
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
441+
}

Diff for: library/std/src/sys/solid/fs.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{abi, error};
22
use crate::{
33
ffi::{CStr, CString, OsStr, OsString},
44
fmt,
5-
io::{self, IoSlice, IoSliceMut, SeekFrom},
5+
io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom},
66
mem::MaybeUninit,
77
os::raw::{c_int, c_short},
88
os::solid::ffi::OsStrExt,
@@ -339,6 +339,32 @@ impl File {
339339
}
340340
}
341341

342+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
343+
unsafe {
344+
let len = buf.remaining();
345+
let mut out_num_bytes = MaybeUninit::uninit();
346+
error::SolidError::err_if_negative(abi::SOLID_FS_Read(
347+
self.fd.raw(),
348+
buf.unfilled_mut().as_mut_ptr() as *mut u8,
349+
len,
350+
out_num_bytes.as_mut_ptr(),
351+
))
352+
.map_err(|e| e.as_io_error())?;
353+
354+
// Safety: `out_num_bytes` is filled by the successful call to
355+
// `SOLID_FS_Read`
356+
let num_bytes_read = out_num_bytes.assume_init();
357+
358+
// Safety: `num_bytes_read` bytes were written to the unfilled
359+
// portion of the buffer
360+
buf.assume_init(num_bytes_read);
361+
362+
buf.add_filled(num_bytes_read);
363+
364+
Ok(())
365+
}
366+
}
367+
342368
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
343369
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
344370
}

Diff for: library/std/src/sys/windows/process.rs

+16
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
704704
// Encode the command and arguments in a command line string such
705705
// that the spawned process may recover them using CommandLineToArgvW.
706706
let mut cmd: Vec<u16> = Vec::new();
707+
708+
// CreateFileW has special handling for .bat and .cmd files, which means we
709+
// need to add an extra pair of quotes surrounding the whole command line
710+
// so they are properly passed on to the script.
711+
// See issue #91991.
712+
let is_batch_file = Path::new(prog)
713+
.extension()
714+
.map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
715+
.unwrap_or(false);
716+
if is_batch_file {
717+
cmd.push(b'"' as u16);
718+
}
719+
707720
// Always quote the program name so CreateProcess doesn't interpret args as
708721
// part of the name if the binary wasn't found first time.
709722
append_arg(&mut cmd, prog, Quote::Always)?;
@@ -715,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
715728
};
716729
append_arg(&mut cmd, arg, quote)?;
717730
}
731+
if is_batch_file {
732+
cmd.push(b'"' as u16);
733+
}
718734
return Ok(cmd);
719735

720736
fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {

Diff for: src/librustdoc/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ crate struct RenderOptions {
272272
crate emit: Vec<EmitType>,
273273
/// If `true`, HTML source pages will generate links for items to their definition.
274274
crate generate_link_to_definition: bool,
275+
/// Set of function-call locations to include as examples
275276
crate call_locations: AllCallLocations,
277+
/// If `true`, Context::init will not emit shared files.
278+
crate no_emit_shared: bool,
276279
}
277280

278281
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -732,6 +735,7 @@ impl Options {
732735
emit,
733736
generate_link_to_definition,
734737
call_locations,
738+
no_emit_shared: false,
735739
},
736740
crate_name,
737741
output_format,

Diff for: src/librustdoc/html/render/context.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
397397
show_type_layout,
398398
generate_link_to_definition,
399399
call_locations,
400+
no_emit_shared,
400401
..
401402
} = options;
402403

@@ -516,13 +517,16 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
516517
sources::render(&mut cx, &krate)?;
517518
}
518519

519-
// Build our search index
520-
let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
520+
if !no_emit_shared {
521+
// Build our search index
522+
let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
523+
524+
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
525+
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
526+
write_shared(&cx, &krate, index, &md_opts)?;
527+
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
528+
}
521529

522-
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
523-
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
524-
write_shared(&cx, &krate, index, &md_opts)?;
525-
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
526530
Ok((cx, krate))
527531
}
528532

Diff for: src/librustdoc/html/static/js/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Rustdoc JS
2+
3+
These JavaScript files are incorporated into the rustdoc binary at build time,
4+
and are minified and written to the filesystem as part of the doc build process.
5+
6+
We use the [Closure Compiler](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
7+
dialect of JSDoc to comment our code and annotate params and return types.
8+
To run a check:
9+
10+
./x.py doc library/std
11+
npm i -g google-closure-compiler
12+
google-closure-compiler -W VERBOSE \
13+
build/<YOUR PLATFORM>/doc/{search-index*.js,crates*.js} \
14+
src/librustdoc/html/static/js/{search.js,main.js,storage.js} \
15+
--externs src/librustdoc/html/static/js/externs.js >/dev/null

Diff for: src/librustdoc/html/static/js/externs.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This file contains type definitions that are processed by the Closure Compiler but are
2+
// not put into the JavaScript we include as part of the documentation. It is used for
3+
// type checking. See README.md in this directory for more info.
4+
5+
/* eslint-disable */
6+
var searchState;
7+
function initSearch(searchIndex){}
8+
9+
/**
10+
* @typedef {{
11+
* raw: string,
12+
* query: string,
13+
* type: string,
14+
* id: string,
15+
* }}
16+
*/
17+
var ParsedQuery;
18+
19+
/**
20+
* @typedef {{
21+
* crate: string,
22+
* desc: string,
23+
* id: number,
24+
* name: string,
25+
* normalizedName: string,
26+
* parent: (Object|null|undefined),
27+
* path: string,
28+
* ty: (Number|null|number),
29+
* type: (Array<?>|null)
30+
* }}
31+
*/
32+
var Row;

0 commit comments

Comments
 (0)