Skip to content

Commit

Permalink
Auto merge of #77372 - jonas-schievink:rollup-e5bdzga, r=jonas-schievink
Browse files Browse the repository at this point in the history
Rollup of 12 pull requests

Successful merges:

 - #77037 (more tiny clippy cleanups)
 - #77233 (BTreeMap: keep an eye out on the size of the main components)
 - #77280 (Ensure that all LLVM components requested by tests are available on CI)
 - #77284 (library: Forward compiler-builtins "mem" feature)
 - #77296 (liveness: Use Option::None to represent absent live nodes)
 - #77322 (Add unstable book docs for `-Zunsound-mir-opts`)
 - #77328 (Use `rtassert!` instead of `assert!` from the child process after fork() in std::sys::unix::process::Command::spawn())
 - #77331 (Add test for async/await combined with const-generics.)
 - #77338 (Fix typo in alloc vec comment)
 - #77340 (Alloc vec use imported path)
 - #77345 (Add test for issue #74761)
 - #77348 (Update books)

Failed merges:

r? `@ghost`
  • Loading branch information
bors committed Sep 30, 2020
2 parents 867bd42 + 3624a90 commit ef663a8
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
// `self.constraints`, but we also want to be mutating
// `self.member_constraints`. For now, just swap out the value
// we want and replace at the end.
let mut tmp =
std::mem::replace(&mut self.constraints.member_constraints, Default::default());
let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
for member_constraint in member_constraints {
tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/transform/early_otherwise_branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
let not_equal_rvalue = Rvalue::BinaryOp(
not_equal,
Operand::Copy(Place::from(second_discriminant_temp)),
Operand::Copy(Place::from(first_descriminant_place)),
Operand::Copy(first_descriminant_place),
);
patch.add_statement(
end_of_block_location,
Expand Down
76 changes: 36 additions & 40 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@
//! - `reader`: the `LiveNode` ID of some node which will read the value
//! that `V` holds on entry to `N`. Formally: a node `M` such
//! that there exists a path `P` from `N` to `M` where `P` does not
//! write `V`. If the `reader` is `INVALID_NODE`, then the current
//! write `V`. If the `reader` is `None`, then the current
//! value will never be read (the variable is dead, essentially).
//!
//! - `writer`: the `LiveNode` ID of some node which will write the
//! variable `V` and which is reachable from `N`. Formally: a node `M`
//! such that there exists a path `P` from `N` to `M` and `M` writes
//! `V`. If the `writer` is `INVALID_NODE`, then there is no writer
//! `V`. If the `writer` is `None`, then there is no writer
//! of `V` that follows `N`.
//!
//! - `used`: a boolean value indicating whether `V` is *used*. We
Expand Down Expand Up @@ -114,7 +114,6 @@ rustc_index::newtype_index! {
rustc_index::newtype_index! {
pub struct LiveNode {
DEBUG_FORMAT = "ln({})",
const INVALID_NODE = LiveNode::MAX_AS_U32,
}
}

Expand Down Expand Up @@ -168,12 +167,6 @@ pub fn provide(providers: &mut Providers) {
// variable must not be assigned if there is some successor
// assignment. And so forth.

impl LiveNode {
fn is_valid(self) -> bool {
self != INVALID_NODE
}
}

struct CaptureInfo {
ln: LiveNode,
var_hid: HirId,
Expand Down Expand Up @@ -467,8 +460,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {

#[derive(Clone, Copy)]
struct RWU {
reader: LiveNode,
writer: LiveNode,
reader: Option<LiveNode>,
writer: Option<LiveNode>,
used: bool,
}

Expand All @@ -490,10 +483,10 @@ struct RWUTable {
unpacked_rwus: Vec<RWU>,
}

// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: false }`.
// A constant representing `RWU { reader: None; writer: None; used: false }`.
const INV_INV_FALSE: u32 = u32::MAX;

// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: true }`.
// A constant representing `RWU { reader: None; writer: None; used: true }`.
const INV_INV_TRUE: u32 = u32::MAX - 1;

impl RWUTable {
Expand All @@ -504,24 +497,24 @@ impl RWUTable {
fn get(&self, idx: usize) -> RWU {
let packed_rwu = self.packed_rwus[idx];
match packed_rwu {
INV_INV_FALSE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: false },
INV_INV_TRUE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: true },
INV_INV_FALSE => RWU { reader: None, writer: None, used: false },
INV_INV_TRUE => RWU { reader: None, writer: None, used: true },
_ => self.unpacked_rwus[packed_rwu as usize],
}
}

fn get_reader(&self, idx: usize) -> LiveNode {
fn get_reader(&self, idx: usize) -> Option<LiveNode> {
let packed_rwu = self.packed_rwus[idx];
match packed_rwu {
INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE,
INV_INV_FALSE | INV_INV_TRUE => None,
_ => self.unpacked_rwus[packed_rwu as usize].reader,
}
}

fn get_writer(&self, idx: usize) -> LiveNode {
fn get_writer(&self, idx: usize) -> Option<LiveNode> {
let packed_rwu = self.packed_rwus[idx];
match packed_rwu {
INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE,
INV_INV_FALSE | INV_INV_TRUE => None,
_ => self.unpacked_rwus[packed_rwu as usize].writer,
}
}
Expand All @@ -541,7 +534,7 @@ impl RWUTable {
}

fn assign_unpacked(&mut self, idx: usize, rwu: RWU) {
if rwu.reader == INVALID_NODE && rwu.writer == INVALID_NODE {
if rwu.reader == None && rwu.writer == None {
// When we overwrite an indexing entry in `self.packed_rwus` with
// `INV_INV_{TRUE,FALSE}` we don't remove the corresponding entry
// from `self.unpacked_rwus`; it's not worth the effort, and we
Expand Down Expand Up @@ -570,7 +563,7 @@ struct Liveness<'a, 'tcx> {
typeck_results: &'a ty::TypeckResults<'tcx>,
param_env: ty::ParamEnv<'tcx>,
upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
successors: IndexVec<LiveNode, LiveNode>,
successors: IndexVec<LiveNode, Option<LiveNode>>,
rwu_table: RWUTable,

/// A live node representing a point of execution before closure entry &
Expand Down Expand Up @@ -606,7 +599,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
typeck_results,
param_env,
upvars,
successors: IndexVec::from_elem_n(INVALID_NODE, num_live_nodes),
successors: IndexVec::from_elem_n(None, num_live_nodes),
rwu_table: RWUTable::new(num_live_nodes * num_vars),
closure_ln,
exit_ln,
Expand Down Expand Up @@ -651,30 +644,33 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}

fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
assert!(ln.is_valid());
let reader = self.rwu_table.get_reader(self.idx(ln, var));
if reader.is_valid() { Some(self.ir.lnks[reader]) } else { None }
if let Some(reader) = self.rwu_table.get_reader(self.idx(ln, var)) {
Some(self.ir.lnks[reader])
} else {
None
}
}

// Is this variable live on entry to any of its successor nodes?
fn live_on_exit(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
let successor = self.successors[ln];
let successor = self.successors[ln].unwrap();
self.live_on_entry(successor, var)
}

fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
assert!(ln.is_valid());
self.rwu_table.get_used(self.idx(ln, var))
}

fn assigned_on_entry(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
assert!(ln.is_valid());
let writer = self.rwu_table.get_writer(self.idx(ln, var));
if writer.is_valid() { Some(self.ir.lnks[writer]) } else { None }
if let Some(writer) = self.rwu_table.get_writer(self.idx(ln, var)) {
Some(self.ir.lnks[writer])
} else {
None
}
}

fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
let successor = self.successors[ln];
let successor = self.successors[ln].unwrap();
self.assigned_on_entry(successor, var)
}

Expand Down Expand Up @@ -709,9 +705,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
{
let wr = &mut wr as &mut dyn Write;
write!(wr, "[{:?} of kind {:?} reads", ln, self.ir.lnks[ln]);
self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_valid());
self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_some());
write!(wr, " writes");
self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_valid());
self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_some());
write!(wr, " uses");
self.write_vars(wr, ln, |idx| self.rwu_table.get_used(idx));

Expand All @@ -735,7 +731,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}

fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) {
self.successors[ln] = succ_ln;
self.successors[ln] = Some(succ_ln);

// It is not necessary to initialize the RWUs here because they are all
// set to INV_INV_FALSE when they are created, and the sets only grow
Expand All @@ -744,7 +740,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) {
// more efficient version of init_empty() / merge_from_succ()
self.successors[ln] = succ_ln;
self.successors[ln] = Some(succ_ln);

self.indices2(ln, succ_ln, |this, idx, succ_idx| {
this.rwu_table.copy_packed(idx, succ_idx);
Expand All @@ -768,12 +764,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let mut changed = false;
let mut rwu = this.rwu_table.get(idx);
let succ_rwu = this.rwu_table.get(succ_idx);
if succ_rwu.reader.is_valid() && !rwu.reader.is_valid() {
if succ_rwu.reader.is_some() && rwu.reader.is_none() {
rwu.reader = succ_rwu.reader;
changed = true
}

if succ_rwu.writer.is_valid() && !rwu.writer.is_valid() {
if succ_rwu.writer.is_some() && rwu.writer.is_none() {
rwu.writer = succ_rwu.writer;
changed = true
}
Expand Down Expand Up @@ -817,14 +813,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let mut rwu = self.rwu_table.get(idx);

if (acc & ACC_WRITE) != 0 {
rwu.reader = INVALID_NODE;
rwu.writer = ln;
rwu.reader = None;
rwu.writer = Some(ln);
}

// Important: if we both read/write, must do read second
// or else the write will override.
if (acc & ACC_READ) != 0 {
rwu.reader = ln;
rwu.reader = Some(ln);
}

if (acc & ACC_USE) != 0 {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_typeck/src/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
wbcx.typeck_results.used_trait_imports = used_trait_imports;

wbcx.typeck_results.closure_captures = mem::replace(
&mut self.typeck_results.borrow_mut().closure_captures,
Default::default(),
);
wbcx.typeck_results.closure_captures =
mem::take(&mut self.typeck_results.borrow_mut().closure_captures);

if self.is_tainted_by_errors() {
// FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
Expand Down
9 changes: 9 additions & 0 deletions library/alloc/src/collections/btree/node/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ fn test_splitpoint() {
assert!(left_len + right_len == CAPACITY);
}
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_sizes() {
assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16);
assert_eq!(core::mem::size_of::<LeafNode<i64, i64>>(), 16 + CAPACITY * 8 * 2);
assert_eq!(core::mem::size_of::<InternalNode<(), ()>>(), 112);
assert_eq!(core::mem::size_of::<InternalNode<i64, i64>>(), 112 + CAPACITY * 8 * 2);
}
4 changes: 2 additions & 2 deletions library/alloc/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2281,14 +2281,14 @@ where

// use try-fold since
// - it vectorizes better for some iterator adapters
// - unlike most internal iteration methods methods it only takes a &mut self
// - unlike most internal iteration methods, it only takes a &mut self
// - it lets us thread the write pointer through its innards and get it back in the end
let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf };
let sink = iterator
.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end))
.unwrap();
// iteration succeeded, don't drop head
let dst = mem::ManuallyDrop::new(sink).dst;
let dst = ManuallyDrop::new(sink).dst;

let src = unsafe { iterator.as_inner().as_into_iter() };
// check if SourceIter contract was upheld
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ gimli-symbolize = []
panic-unwind = ["panic_unwind"]
profiler = ["profiler_builtins"]
compiler-builtins-c = ["alloc/compiler-builtins-c"]
compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
llvm-libunwind = ["unwind/llvm-libunwind"]

# Make panics and failed asserts immediately abort without formatting any message
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/unix/process/process_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl Command {
// pipe I/O up to PIPE_BUF bytes should be atomic, and then
// we want to be sure we *don't* run at_exit destructors as
// we're being torn down regardless
assert!(output.write(&bytes).is_ok());
rtassert!(output.write(&bytes).is_ok());
libc::_exit(1)
}
n => n,
Expand Down
1 change: 1 addition & 0 deletions library/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ proc_macro = { path = "../proc_macro" }
default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
backtrace = ["std/backtrace"]
compiler-builtins-c = ["std/compiler-builtins-c"]
compiler-builtins-mem = ["std/compiler-builtins-mem"]
llvm-libunwind = ["std/llvm-libunwind"]
panic-unwind = ["std/panic_unwind"]
panic_immediate_abort = ["std/panic_immediate_abort"]
Expand Down
2 changes: 2 additions & 0 deletions src/ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools"
fi

export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1

# Print the date from the local machine and the date from an external source to
# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure
# Pipelines it happened that the certificates were marked as expired.
Expand Down
2 changes: 1 addition & 1 deletion src/doc/embedded-book
8 changes: 8 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# `unsound-mir-opts`

--------------------

The `-Zunsound-mir-opts` compiler flag enables [MIR optimization passes] which can cause unsound behavior.
This flag should only be used by MIR optimization tests in the rustc test suite.

[MIR optimization passes]: https://rustc-dev-guide.rust-lang.org/mir/optimizations.html
25 changes: 25 additions & 0 deletions src/test/ui/const-generics/issue-74906.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// edition:2018
// check-pass
// revisions: full min
#![cfg_attr(full, feature(const_generics))]
#![cfg_attr(full, allow(incomplete_features))]
#![cfg_attr(min, feature(min_const_generics))]

const SIZE: usize = 16;

struct Bar<const H: usize> {}

struct Foo<const H: usize> {}

impl<const H: usize> Foo<H> {
async fn biz(_: &[[u8; SIZE]]) -> Vec<()> {
vec![]
}

pub async fn baz(&self) -> Bar<H> {
Self::biz(&vec![]).await;
Bar {}
}
}

fn main() { }
16 changes: 16 additions & 0 deletions src/test/ui/type-alias-impl-trait/issue-74761.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(member_constraints)]
#![feature(type_alias_impl_trait)]

pub trait A {
type B;
fn f(&self) -> Self::B;
}
impl<'a, 'b> A for () {
//~^ ERROR the lifetime parameter `'a` is not constrained
//~| ERROR the lifetime parameter `'b` is not constrained
type B = impl core::fmt::Debug;

fn f(&self) -> Self::B {}
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/type-alias-impl-trait/issue-74761.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:8:6
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter

error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:8:10
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0207`.
Loading

0 comments on commit ef663a8

Please sign in to comment.