Skip to content

Commit

Permalink
Auto merge of #113508 - matthiaskrgr:rollup-xzrp4nt, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #111618 (Always name the return place.)
 - #113247 (Add Tests for native wasm exceptions)
 - #113273 (Use String or Int to set the opt level)
 - #113469 (Remove `default_free_fn` feature)
 - #113493 (additional io::copy specializations)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 9, 2023
2 parents b12ff66 + 205ae16 commit a9eba8d
Show file tree
Hide file tree
Showing 44 changed files with 758 additions and 323 deletions.
3 changes: 1 addition & 2 deletions compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

let local_ref = &self.locals[local];

// FIXME Should the return place be named?
let name = if bx.sess().fewer_names() || local == mir::RETURN_PLACE {
let name = if bx.sess().fewer_names() {
None
} else {
Some(match whole_local_var.or(fallback_var.clone()) {
Expand Down
14 changes: 12 additions & 2 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,20 @@ changelog-seen = 2
# =============================================================================
[rust]

# Whether or not to optimize the compiler and standard library.
# Whether or not to optimize when compiling the compiler and standard library,
# and what level of optimization to use.
# WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping,
# building without optimizations takes much longer than optimizing. Further, some platforms
# fail to build without this optimization (c.f. #65352).
# The valid options are:
# true - Enable optimizations.
# false - Disable optimizations.
# 0 - Disable optimizations.
# 1 - Basic optimizations.
# 2 - Some optimizations.
# 3 - All optimizations.
# "s" - Optimize for binary size.
# "z" - Optimize for binary size, but also turn off loop vectorization.
#optimize = true

# Indicates that the build should be configured for debugging Rust. A
Expand Down Expand Up @@ -757,7 +767,7 @@ changelog-seen = 2
# This option will override the same option under [build] section.
#profiler = build.profiler (bool)

# This option supports enable `rpath` in each target independently,
# This option supports enable `rpath` in each target independently,
# and will override the same option under [rust] section. It only works on Unix platforms
#rpath = rust.rpath (bool)

Expand Down
45 changes: 0 additions & 45 deletions library/core/src/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,51 +133,6 @@ pub trait Default: Sized {
fn default() -> Self;
}

/// Return the default value of a type according to the `Default` trait.
///
/// The type to return is inferred from context; this is equivalent to
/// `Default::default()` but shorter to type.
///
/// For example:
/// ```
/// #![feature(default_free_fn)]
///
/// use std::default::default;
///
/// #[derive(Default)]
/// struct AppConfig {
/// foo: FooConfig,
/// bar: BarConfig,
/// }
///
/// #[derive(Default)]
/// struct FooConfig {
/// foo: i32,
/// }
///
/// #[derive(Default)]
/// struct BarConfig {
/// bar: f32,
/// baz: u8,
/// }
///
/// fn main() {
/// let options = AppConfig {
/// foo: default(),
/// bar: BarConfig {
/// bar: 10.1,
/// ..default()
/// },
/// };
/// }
/// ```
#[unstable(feature = "default_free_fn", issue = "73014")]
#[must_use]
#[inline]
pub fn default<T: Default>() -> T {
Default::default()
}

/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro(Default, attributes(default))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
Expand Down
81 changes: 79 additions & 2 deletions library/std/src/io/copy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use super::{BorrowedBuf, BufReader, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE};
use crate::alloc::Allocator;
use crate::cmp;
use crate::collections::VecDeque;
use crate::io::IoSlice;
use crate::mem::MaybeUninit;

#[cfg(test)]
Expand Down Expand Up @@ -86,7 +90,7 @@ where

/// Specialization of the read-write loop that reuses the internal
/// buffer of a BufReader. If there's no buffer then the writer side
/// should be used intead.
/// should be used instead.
trait BufferedReaderSpec {
fn buffer_size(&self) -> usize;

Expand All @@ -104,7 +108,39 @@ where
}

default fn copy_to(&mut self, _to: &mut (impl Write + ?Sized)) -> Result<u64> {
unimplemented!("only called from specializations");
unreachable!("only called from specializations")
}
}

impl BufferedReaderSpec for &[u8] {
fn buffer_size(&self) -> usize {
// prefer this specialization since the source "buffer" is all we'll ever need,
// even if it's small
usize::MAX
}

fn copy_to(&mut self, to: &mut (impl Write + ?Sized)) -> Result<u64> {
let len = self.len();
to.write_all(self)?;
*self = &self[len..];
Ok(len as u64)
}
}

impl<A: Allocator> BufferedReaderSpec for VecDeque<u8, A> {
fn buffer_size(&self) -> usize {
// prefer this specialization since the source "buffer" is all we'll ever need,
// even if it's small
usize::MAX
}

fn copy_to(&mut self, to: &mut (impl Write + ?Sized)) -> Result<u64> {
let len = self.len();
let (front, back) = self.as_slices();
let bufs = &mut [IoSlice::new(front), IoSlice::new(back)];
to.write_all_vectored(bufs)?;
self.clear();
Ok(len as u64)
}
}

Expand Down Expand Up @@ -218,6 +254,47 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> {
}
}

impl<A: Allocator> BufferedWriterSpec for Vec<u8, A> {
fn buffer_size(&self) -> usize {
cmp::max(DEFAULT_BUF_SIZE, self.capacity() - self.len())
}

fn copy_from<R: Read + ?Sized>(&mut self, reader: &mut R) -> Result<u64> {
let mut bytes = 0;

// avoid allocating before we have determined that there's anything to read
if self.capacity() == 0 {
bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?;
if bytes == 0 {
return Ok(0);
}
}

loop {
self.reserve(DEFAULT_BUF_SIZE);
let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into();
match reader.read_buf(buf.unfilled()) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};

let read = buf.filled().len();
if read == 0 {
break;
}

// SAFETY: BorrowedBuf guarantees all of its filled bytes are init
// and the number of read bytes can't exceed the spare capacity since
// that's what the buffer is borrowing from.
unsafe { self.set_len(self.len() + read) };
bytes += read as u64;
}

Ok(bytes)
}
}

fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
reader: &mut R,
writer: &mut W,
Expand Down
38 changes: 37 additions & 1 deletion library/std/src/io/copy/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::cmp::{max, min};
use crate::collections::VecDeque;
use crate::io;
use crate::io::*;

#[test]
Expand All @@ -19,7 +21,7 @@ struct ShortReader {

impl Read for ShortReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let bytes = min(self.cap, self.read_size);
let bytes = min(self.cap, self.read_size).min(buf.len());
self.cap -= bytes;
self.observed_buffer = max(self.observed_buffer, buf.len());
Ok(bytes)
Expand Down Expand Up @@ -78,6 +80,40 @@ fn copy_specializes_bufreader() {
);
}

#[test]
fn copy_specializes_to_vec() {
let cap = 123456;
let mut source = ShortReader { cap, observed_buffer: 0, read_size: 1337 };
let mut sink = Vec::new();
assert_eq!(cap as u64, io::copy(&mut source, &mut sink).unwrap());
assert!(
source.observed_buffer > DEFAULT_BUF_SIZE,
"expected a large buffer to be provided to the reader"
);
}

#[test]
fn copy_specializes_from_vecdeque() {
let mut source = VecDeque::with_capacity(100 * 1024);
for _ in 0..20 * 1024 {
source.push_front(0);
}
for _ in 0..20 * 1024 {
source.push_back(0);
}
let mut sink = WriteObserver { observed_buffer: 0 };
assert_eq!(40 * 1024u64, io::copy(&mut source, &mut sink).unwrap());
assert_eq!(20 * 1024, sink.observed_buffer);
}

#[test]
fn copy_specializes_from_slice() {
let mut source = [1; 60 * 1024].as_slice();
let mut sink = WriteObserver { observed_buffer: 0 };
assert_eq!(60 * 1024u64, io::copy(&mut source, &mut sink).unwrap());
assert_eq!(60 * 1024, sink.observed_buffer);
}

#[cfg(unix)]
mod io_benches {
use crate::fs::File;
Expand Down
73 changes: 60 additions & 13 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,11 +875,10 @@ impl Default for StringOrBool {
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RustOptimize {
#[serde(deserialize_with = "deserialize_and_validate_opt_level")]
String(String),
Int(u8),
Bool(bool),
}

Expand All @@ -889,26 +888,74 @@ impl Default for RustOptimize {
}
}

fn deserialize_and_validate_opt_level<'de, D>(d: D) -> Result<String, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let v = String::deserialize(d)?;
if ["0", "1", "2", "3", "s", "z"].iter().find(|x| **x == v).is_some() {
Ok(v)
} else {
Err(format!(r#"unrecognized option for rust optimize: "{}", expected one of "0", "1", "2", "3", "s", "z""#, v)).map_err(serde::de::Error::custom)
impl<'de> Deserialize<'de> for RustOptimize {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(OptimizeVisitor)
}
}

struct OptimizeVisitor;

impl<'de> serde::de::Visitor<'de> for OptimizeVisitor {
type Value = RustOptimize;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(r#"one of: 0, 1, 2, 3, "s", "z", true, false"#)
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if ["s", "z"].iter().find(|x| **x == value).is_some() {
Ok(RustOptimize::String(value.to_string()))
} else {
Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom)
}
}

fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if matches!(value, 0..=3) {
Ok(RustOptimize::Int(value as u8))
} else {
Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom)
}
}

fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(RustOptimize::Bool(value))
}
}

fn format_optimize_error_msg(v: impl std::fmt::Display) -> String {
format!(
r#"unrecognized option for rust optimize: "{}", expected one of 0, 1, 2, 3, "s", "z", true, false"#,
v
)
}

impl RustOptimize {
pub(crate) fn is_release(&self) -> bool {
if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false }
match &self {
RustOptimize::Bool(true) | RustOptimize::String(_) => true,
RustOptimize::Int(i) => *i > 0,
RustOptimize::Bool(false) => false,
}
}

pub(crate) fn get_opt_level(&self) -> Option<String> {
match &self {
RustOptimize::String(s) => Some(s.clone()),
RustOptimize::Int(i) => Some(i.to_string()),
RustOptimize::Bool(_) => None,
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/bootstrap/config/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,10 @@ fn rust_optimize() {
assert_eq!(parse("").rust_optimize.is_release(), true);
assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false);
assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true);
assert_eq!(parse("rust.optimize = \"1\"").rust_optimize.get_opt_level(), Some("1".to_string()));
assert_eq!(parse("rust.optimize = 0").rust_optimize.is_release(), false);
assert_eq!(parse("rust.optimize = 1").rust_optimize.is_release(), true);
assert_eq!(parse("rust.optimize = 1").rust_optimize.get_opt_level(), Some("1".to_string()));
assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.is_release(), true);
assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string()));
}

Expand Down
6 changes: 4 additions & 2 deletions src/ci/docker/host-x86_64/test-various/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
qemu-system-x86 \
&& rm -rf /var/lib/apt/lists/*

RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \
RUN curl -sL https://nodejs.org/dist/v18.12.0/node-v18.12.0-linux-x64.tar.xz | \
tar -xJ

# Install 32-bit OVMF files for the i686-unknown-uefi test. This package
Expand All @@ -42,7 +42,7 @@ RUN sh /scripts/sccache.sh

ENV RUST_CONFIGURE_ARGS \
--musl-root-x86_64=/usr/local/x86_64-linux-musl \
--set build.nodejs=/node-v15.14.0-linux-x64/bin/node \
--set build.nodejs=/node-v18.12.0-linux-x64/bin/node \
--set rust.lld

# Some run-make tests have assertions about code size, and enabling debug
Expand All @@ -58,6 +58,8 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T
tests/ui \
tests/mir-opt \
tests/codegen-units \
tests/codegen \
tests/assembly \
library/core

ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
Expand Down
Loading

0 comments on commit a9eba8d

Please sign in to comment.