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 5 pull requests #105841

Closed
wants to merge 11 commits into from
Closed
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ E0311: include_str!("./error_codes/E0311.md"),
E0312: include_str!("./error_codes/E0312.md"),
E0316: include_str!("./error_codes/E0316.md"),
E0317: include_str!("./error_codes/E0317.md"),
E0320: include_str!("./error_codes/E0320.md"),
E0321: include_str!("./error_codes/E0321.md"),
E0322: include_str!("./error_codes/E0322.md"),
E0323: include_str!("./error_codes/E0323.md"),
Expand Down Expand Up @@ -575,7 +576,6 @@ E0791: include_str!("./error_codes/E0791.md"),
// E0314, // closure outlives stack frame
// E0315, // cannot invoke closure outside of its lifetime
// E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0320.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Recursion limit reached while creating drop-check rules.

Example of erroneous code:

```compile_fail,E0320
enum A<T> {
B,
C(T, Box<A<(T, T)>>)
}

fn foo<T>() {
A::<T>::B; // error: overflow while adding drop-check rules for A<T>
}
```

The Rust compiler must be able to reason about how a type is [`Drop`]ped, and
by extension the types of its fields, to be able to generate the glue to
properly drop a value. The code example above shows a type where this inference
is impossible because it is recursive. Note that this is *not* the same as
[E0072](E0072.html), where a type has an infinite size; the type here has a
finite size but any attempt to `Drop` it would recurse infinitely. For more
information, read [the `Drop` docs](../std/ops/trait.Drop.html).

It is not possible to define a type with recursive drop-check rules. All such
recursion must be removed.

[`Drop`]: ../std/ops/trait.Drop.html
49 changes: 49 additions & 0 deletions compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
@call("mir_goto", args) => {
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
},
@call("mir_unreachable", _args) => {
Ok(TerminatorKind::Unreachable)
},
@call("mir_drop", args) => {
Ok(TerminatorKind::Drop {
place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?,
unwind: None,
})
},
@call("mir_drop_and_replace", args) => {
Ok(TerminatorKind::DropAndReplace {
place: self.parse_place(args[0])?,
value: self.parse_operand(args[1])?,
target: self.parse_block(args[2])?,
unwind: None,
})
},
@call("mir_call", args) => {
let destination = self.parse_place(args[0])?;
let target = self.parse_block(args[1])?;
self.parse_call(args[2], destination, target)
},
ExprKind::Match { scrutinee, arms } => {
let discr = self.parse_operand(*scrutinee)?;
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
Expand Down Expand Up @@ -86,6 +109,32 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
}

fn parse_call(
&self,
expr_id: ExprId,
destination: Place<'tcx>,
target: BasicBlock,
) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, expr_id, _, "function call",
ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
let fun = self.parse_operand(*fun)?;
let args = args
.iter()
.map(|arg| self.parse_operand(*arg))
.collect::<PResult<Vec<_>>>()?;
Ok(TerminatorKind::Call {
func: fun,
args,
destination,
target: Some(target),
cleanup: None,
from_hir_call: *from_hir_call,
fn_span: *fn_span,
})
},
)
}

fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, _, "rvalue",
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
Expand Down
39 changes: 37 additions & 2 deletions library/core/src/intrinsics/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
//! "runtime", phase = "optimized")] if you don't.
//!
//! [dialect docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
//! [dialect docs]:
//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
//!
//! The input to the [`mir!`] macro is:
//!
Expand Down Expand Up @@ -99,6 +100,30 @@
//! Return()
//! })
//! }
//!
//! #[custom_mir(dialect = "runtime", phase = "optimized")]
//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
//! mir!(
//! let unused;
//! let popped;
//!
//! {
//! Call(unused, pop, Vec::push(v, value))
//! }
//!
//! pop = {
//! Call(popped, drop, Vec::pop(v))
//! }
//!
//! drop = {
//! Drop(popped, ret)
//! }
//!
//! ret = {
//! Return()
//! }
//! )
//! }
//! ```
//!
//! We can also set off compilation failures that happen in sufficiently late stages of the
Expand Down Expand Up @@ -195,10 +220,16 @@
//!
//! #### Terminators
//!
//! - [`Goto`] and [`Return`] have associated functions.
//! Custom MIR does not currently support cleanup blocks or non-trivial unwind paths. As such, there
//! are no resume and abort terminators, and terminators that might unwind do not have any way to
//! indicate the unwind block.
//!
//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions.
//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
//! otherwise branch.
//! - [`Call`] has an associated function as well. The third argument of this function is a normal
//! function call expresion, for example `my_other_function(a, 5)`.
//!

#![unstable(
Expand All @@ -223,6 +254,10 @@ macro_rules! define {

define!("mir_return", fn Return() -> BasicBlock);
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
define!("mir_unreachable", fn Unreachable() -> BasicBlock);
define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_retag_raw", fn RetagRaw<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
Expand Down
10 changes: 6 additions & 4 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ impl Read for ChildStdout {
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
}

impl AsInner<AnonPipe> for ChildStdout {
Expand Down Expand Up @@ -907,10 +911,8 @@ impl Command {
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> {
self.inner
.spawn(imp::Stdio::MakePipe, false)
.map(Child::from_inner)
.and_then(|p| p.wait_with_output())
let (status, stdout, stderr) = self.inner.output()?;
Ok(Output { status: ExitStatus(status), stdout, stderr })
}

/// Executes a command as a child process, waiting for it to finish and
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/unix/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ impl AnonPipe {
self.0.is_read_vectored()
}

pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}

pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/unix/process/process_fuchsia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ impl Command {
Ok((Process { handle: Handle::new(process_handle) }, ours))
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
crate::sys_common::process::wait_with_output(proc, pipes)
}

pub fn exec(&mut self, default: Stdio) -> io::Error {
if self.saw_nul() {
return io::const_io_error!(
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/unix/process/process_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ impl Command {
}
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
crate::sys_common::process::wait_with_output(proc, pipes)
}

// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
#[cfg(not(target_os = "linux"))]
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/unix/process/process_unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ impl Command {
unsupported()
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
unsupported()
}

pub fn exec(&mut self, _default: Stdio) -> io::Error {
unsupported_err()
}
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/unix/process/process_vxworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ impl Command {
}
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
crate::sys_common::process::wait_with_output(proc, pipes)
}

pub fn exec(&mut self, default: Stdio) -> io::Error {
let ret = Command::spawn(self, default, false);
match ret {
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/unsupported/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ impl AnonPipe {
self.0
}

pub fn read_to_end(&self, _buf: &mut Vec<u8>) -> io::Result<usize> {
self.0
}

pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
self.0
}
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/unsupported/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ impl Command {
) -> io::Result<(Process, StdioPipes)> {
unsupported()
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
unsupported()
}
}

impl From<AnonPipe> for Stdio {
Expand Down
6 changes: 5 additions & 1 deletion library/std/src/sys/windows/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::os::windows::prelude::*;

use crate::ffi::OsStr;
use crate::io::{self, IoSlice, IoSliceMut};
use crate::io::{self, IoSlice, IoSliceMut, Read};
use crate::mem;
use crate::path::Path;
use crate::ptr;
Expand Down Expand Up @@ -261,6 +261,10 @@ impl AnonPipe {
self.inner.is_read_vectored()
}

pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.handle().read_to_end(buf)
}

pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
unsafe {
let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ impl Command {
))
}
}

pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
crate::sys_common::process::wait_with_output(proc, pipes)
}
}

impl fmt::Debug for Command {
Expand Down
31 changes: 30 additions & 1 deletion library/std/src/sys_common/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
use crate::collections::BTreeMap;
use crate::env;
use crate::ffi::{OsStr, OsString};
use crate::sys::process::EnvKey;
use crate::io;
use crate::sys::pipe::read2;
use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};

// Stores a set of changes to an environment
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -117,3 +119,30 @@ impl<'a> ExactSizeIterator for CommandEnvs<'a> {
self.iter.is_empty()
}
}

pub fn wait_with_output(
mut process: Process,
mut pipes: StdioPipes,
) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
drop(pipes.stdin.take());

let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
match (pipes.stdout.take(), pipes.stderr.take()) {
(None, None) => {}
(Some(out), None) => {
let res = out.read_to_end(&mut stdout);
res.unwrap();
}
(None, Some(err)) => {
let res = err.read_to_end(&mut stderr);
res.unwrap();
}
(Some(out), Some(err)) => {
let res = read2(out, &mut stdout, err, &mut stderr);
res.unwrap();
}
}

let status = process.wait()?;
Ok((status, stdout, stderr))
}
1 change: 1 addition & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ impl<'a> Builder<'a> {
install::RustDemangler,
install::Clippy,
install::Miri,
install::LlvmTools,
install::Analysis,
install::Src,
install::Rustc
Expand Down
6 changes: 6 additions & 0 deletions src/bootstrap/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ install!((self, builder, _config),
.expect("missing miri");
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
};
LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
let tarball = builder
.ensure(dist::LlvmTools { target: self.target })
.expect("missing llvm-tools");
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
};
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
compiler: self.compiler,
Expand Down
Loading