Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #92216

Merged
merged 15 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,11 +1195,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn suggest_derive(
&self,
err: &mut DiagnosticBuilder<'_>,
unsatisfied_predicates: &Vec<(
unsatisfied_predicates: &[(
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)>,
)],
) {
let mut derives = Vec::<(String, Span, String)>::new();
let mut traits = Vec::<Span>::new();
Expand Down Expand Up @@ -1236,23 +1236,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
traits.push(self.tcx.def_span(trait_pred.def_id()));
}
}
derives.sort();
let derives_grouped = derives.into_iter().fold(
Vec::<(String, Span, String)>::new(),
|mut acc, (self_name, self_span, trait_name)| {
if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
if acc_self_name == &self_name {
traits.push_str(format!(", {}", trait_name).as_str());
return acc;
}
}
acc.push((self_name, self_span, trait_name));
acc
},
);
traits.sort();
traits.dedup();

derives.sort();
derives.dedup();

let mut derives_grouped = Vec::<(String, Span, String)>::new();
for (self_name, self_span, trait_name) in derives.into_iter() {
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
{
if last_self_name == &self_name {
last_trait_names.push_str(format!(", {}", trait_name).as_str());
continue;
}
}
derives_grouped.push((self_name, self_span, trait_name));
}

let len = traits.len();
if len > 0 {
let span: MultiSpan = traits.into();
Expand Down
31 changes: 31 additions & 0 deletions library/alloc/tests/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,37 @@ fn test_rev_iterator() {
assert_eq!(pos, v.len());
}

#[test]
fn test_to_lowercase_rev_iterator() {
let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ";
let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a'];

let mut pos = 0;
let it = s.chars().flat_map(|c| c.to_lowercase()).rev();

for c in it {
assert_eq!(c, v[pos]);
pos += 1;
}
assert_eq!(pos, v.len());
}

#[test]
fn test_to_uppercase_rev_iterator() {
let s = "aößü💩στιγμαςDžfiᾀ";
let v =
['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A'];

let mut pos = 0;
let it = s.chars().flat_map(|c| c.to_uppercase()).rev();

for c in it {
assert_eq!(c, v[pos]);
pos += 1;
}
assert_eq!(pos, v.len());
}

#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_chars_decoding() {
Expand Down
34 changes: 34 additions & 0 deletions library/core/src/char/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,13 @@ impl Iterator for ToLowercase {
}
}

#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
impl DoubleEndedIterator for ToLowercase {
fn next_back(&mut self) -> Option<char> {
self.0.next_back()
}
}

#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for ToLowercase {}

Expand Down Expand Up @@ -420,6 +427,13 @@ impl Iterator for ToUppercase {
}
}

#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
impl DoubleEndedIterator for ToUppercase {
fn next_back(&mut self) -> Option<char> {
self.0.next_back()
}
}

#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for ToUppercase {}

Expand Down Expand Up @@ -479,6 +493,26 @@ impl Iterator for CaseMappingIter {
}
}

impl DoubleEndedIterator for CaseMappingIter {
fn next_back(&mut self) -> Option<char> {
match *self {
CaseMappingIter::Three(a, b, c) => {
*self = CaseMappingIter::Two(a, b);
Some(c)
}
CaseMappingIter::Two(b, c) => {
*self = CaseMappingIter::One(b);
Some(c)
}
CaseMappingIter::One(c) => {
*self = CaseMappingIter::Zero;
Some(c)
}
CaseMappingIter::Zero => None,
}
}
}

impl fmt::Display for CaseMappingIter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Expand Down
6 changes: 6 additions & 0 deletions library/core/tests/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ fn test_to_lowercase() {
let iter: String = c.to_lowercase().collect();
let disp: String = c.to_lowercase().to_string();
assert_eq!(iter, disp);
let iter_rev: String = c.to_lowercase().rev().collect();
let disp_rev: String = disp.chars().rev().collect();
assert_eq!(iter_rev, disp_rev);
iter
}
assert_eq!(lower('A'), "a");
Expand Down Expand Up @@ -130,6 +133,9 @@ fn test_to_uppercase() {
let iter: String = c.to_uppercase().collect();
let disp: String = c.to_uppercase().to_string();
assert_eq!(iter, disp);
let iter_rev: String = c.to_uppercase().rev().collect();
let disp_rev: String = disp.chars().rev().collect();
assert_eq!(iter_rev, disp_rev);
iter
}
assert_eq!(upper('a'), "A");
Expand Down
6 changes: 3 additions & 3 deletions library/std/src/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ use crate::cell::UnsafeCell;
use crate::env;
use crate::ffi::c_void;
use crate::fmt;
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use crate::sync::Once;
use crate::sys_common::backtrace::{lock, output_filename};
use crate::vec::Vec;
Expand Down Expand Up @@ -256,7 +256,7 @@ impl Backtrace {
// backtrace captures speedy, because otherwise reading environment
// variables every time can be somewhat slow.
static ENABLED: AtomicUsize = AtomicUsize::new(0);
match ENABLED.load(SeqCst) {
match ENABLED.load(Relaxed) {
0 => {}
1 => return false,
_ => return true,
Expand All @@ -268,7 +268,7 @@ impl Backtrace {
Err(_) => false,
},
};
ENABLED.store(enabled as usize + 1, SeqCst);
ENABLED.store(enabled as usize + 1, Relaxed);
enabled
}

Expand Down
19 changes: 19 additions & 0 deletions library/std/src/process/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,22 @@ fn env_empty() {
let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
assert!(p.is_ok());
}

// See issue #91991
#[test]
#[cfg(windows)]
fn run_bat_script() {
let tempdir = crate::sys_common::io::test::tmpdir();
let script_path = tempdir.join("hello.cmd");

crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap();
let output = Command::new(&script_path)
.arg("fellow Rustaceans")
.stdout(crate::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
}
28 changes: 27 additions & 1 deletion library/std/src/sys/solid/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{abi, error};
use crate::{
ffi::{CStr, CString, OsStr, OsString},
fmt,
io::{self, IoSlice, IoSliceMut, SeekFrom},
io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom},
mem::MaybeUninit,
os::raw::{c_int, c_short},
os::solid::ffi::OsStrExt,
Expand Down Expand Up @@ -339,6 +339,32 @@ impl File {
}
}

pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
unsafe {
let len = buf.remaining();
let mut out_num_bytes = MaybeUninit::uninit();
error::SolidError::err_if_negative(abi::SOLID_FS_Read(
self.fd.raw(),
buf.unfilled_mut().as_mut_ptr() as *mut u8,
len,
out_num_bytes.as_mut_ptr(),
))
.map_err(|e| e.as_io_error())?;

// Safety: `out_num_bytes` is filled by the successful call to
// `SOLID_FS_Read`
let num_bytes_read = out_num_bytes.assume_init();

// Safety: `num_bytes_read` bytes were written to the unfilled
// portion of the buffer
buf.assume_init(num_bytes_read);

buf.add_filled(num_bytes_read);

Ok(())
}
}

pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
}
Expand Down
16 changes: 16 additions & 0 deletions library/std/src/sys/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
// Encode the command and arguments in a command line string such
// that the spawned process may recover them using CommandLineToArgvW.
let mut cmd: Vec<u16> = Vec::new();

// CreateFileW has special handling for .bat and .cmd files, which means we
// need to add an extra pair of quotes surrounding the whole command line
// so they are properly passed on to the script.
// See issue #91991.
let is_batch_file = Path::new(prog)
.extension()
.map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
.unwrap_or(false);
if is_batch_file {
cmd.push(b'"' as u16);
}

// Always quote the program name so CreateProcess doesn't interpret args as
// part of the name if the binary wasn't found first time.
append_arg(&mut cmd, prog, Quote::Always)?;
Expand All @@ -715,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
};
append_arg(&mut cmd, arg, quote)?;
}
if is_batch_file {
cmd.push(b'"' as u16);
}
return Ok(cmd);

fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
Expand Down
4 changes: 4 additions & 0 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ crate struct RenderOptions {
crate emit: Vec<EmitType>,
/// If `true`, HTML source pages will generate links for items to their definition.
crate generate_link_to_definition: bool,
/// Set of function-call locations to include as examples
crate call_locations: AllCallLocations,
/// If `true`, Context::init will not emit shared files.
crate no_emit_shared: bool,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -732,6 +735,7 @@ impl Options {
emit,
generate_link_to_definition,
call_locations,
no_emit_shared: false,
},
crate_name,
output_format,
Expand Down
16 changes: 10 additions & 6 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
show_type_layout,
generate_link_to_definition,
call_locations,
no_emit_shared,
..
} = options;

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

// Build our search index
let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
if !no_emit_shared {
// Build our search index
let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);

// Write shared runs within a flock; disable thread dispatching of IO temporarily.
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
write_shared(&cx, &krate, index, &md_opts)?;
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
}

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

Expand Down
15 changes: 15 additions & 0 deletions src/librustdoc/html/static/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Rustdoc JS

These JavaScript files are incorporated into the rustdoc binary at build time,
and are minified and written to the filesystem as part of the doc build process.

We use the [Closure Compiler](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
dialect of JSDoc to comment our code and annotate params and return types.
To run a check:

./x.py doc library/std
npm i -g google-closure-compiler
google-closure-compiler -W VERBOSE \
build/<YOUR PLATFORM>/doc/{search-index*.js,crates*.js} \
src/librustdoc/html/static/js/{search.js,main.js,storage.js} \
--externs src/librustdoc/html/static/js/externs.js >/dev/null
32 changes: 32 additions & 0 deletions src/librustdoc/html/static/js/externs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file contains type definitions that are processed by the Closure Compiler but are
// not put into the JavaScript we include as part of the documentation. It is used for
// type checking. See README.md in this directory for more info.

/* eslint-disable */
var searchState;
function initSearch(searchIndex){}

/**
* @typedef {{
* raw: string,
* query: string,
* type: string,
* id: string,
* }}
*/
var ParsedQuery;

/**
* @typedef {{
* crate: string,
* desc: string,
* id: number,
* name: string,
* normalizedName: string,
* parent: (Object|null|undefined),
* path: string,
* ty: (Number|null|number),
* type: (Array<?>|null)
* }}
*/
var Row;
Loading