Skip to content

Commit

Permalink
Auto merge of #70931 - Dylan-DPC:rollup-f8orcao, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - #70789 (remove false positives of unused_braces)
 - #70847 (ci: move /var/lib/docker to /mnt on GHA)
 - #70850 (BTreeMap first last proposal tweaks)
 - #70876 (Use a `SmallVec` for `Cache::predecessors`.)
 - #70883 (Clean up E0507 explanation)
 - #70892 (wf: refactor `compute_trait_ref`)
 - #70914 (Corrects a typo in rustdoc documentation.)
 - #70915 (Remove unnecessary TypeFlags::NOMINAL_FLAGS)
 - #70927 (Clean up E0510 explanation)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Apr 8, 2020
2 parents 42abbd8 + 1498da8 commit 485c5fb
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 273 deletions.
6 changes: 6 additions & 0 deletions src/ci/scripts/symlink-build-dir.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ elif isLinux && isGitHubActions; then
mv "${current_dir}" /mnt/more-space/workspace
ln -s /mnt/more-space/workspace "${current_dir}"
cd "${current_dir}"

# Move the Docker data directory to /mnt
sudo systemctl stop docker.service
sudo mv /var/lib/docker /mnt/docker
sudo ln -s /mnt/docker /var/lib/docker
sudo systemctl start docker.service
fi
6 changes: 3 additions & 3 deletions src/doc/rustdoc/src/documentation-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,9 @@ are added.
/// ```
```
`edition2018` tells `rustdoc` that the code sample should be compiled the 2018
edition of Rust. Similarly, you can specify `edition2015` to compile the code
with the 2015 edition.
`edition2018` tells `rustdoc` that the code sample should be compiled using
the 2018 edition of Rust. Similarly, you can specify `edition2015` to compile
the code with the 2015 edition.
## Syntax reference
Expand Down
124 changes: 76 additions & 48 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv)
}
Expand All @@ -667,36 +663,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.first_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.first_entry() {
/// if *entry.key() > 0 {
/// entry.insert("first");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "first");
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
if let Ok(kv) = front.right_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = front.right_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the first element in the map.
/// The key of this element is the minimum key that was in the map.
///
/// # Examples
///
/// Draining elements in ascending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_first() {
/// assert!(map.iter().all(|(k, _v)| *k > key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_first(&mut self) -> Option<(K, V)> {
self.first_entry().map(|entry| entry.remove_entry())
}

/// Returns the last key-value pair in the map.
Expand All @@ -716,11 +730,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv)
}
Expand All @@ -730,36 +740,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.last_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.last_entry() {
/// if *entry.key() > 0 {
/// entry.insert("last");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "a");
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
if let Ok(kv) = back.left_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = back.left_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the last element in the map.
/// The key of this element is the maximum key that was in the map.
///
/// # Examples
///
/// Draining elements in descending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_last() {
/// assert!(map.iter().all(|(k, _v)| *k < key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_last(&mut self) -> Option<(K, V)> {
self.last_entry().map(|entry| entry.remove_entry())
}

/// Returns `true` if the map contains a value for the specified key.
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_error_codes/error_codes/E0507.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
You tried to move out of a value which was borrowed.

This can also happen when using a type implementing `Fn` or `FnMut`, as neither
allows moving out of them (they usually represent closures which can be called
more than once). Much of the text following applies equally well to non-`FnOnce`
closure bodies.
A borrowed value was moved out.

Erroneous code example:

Expand Down Expand Up @@ -32,6 +27,11 @@ you have three choices:
* Somehow reclaim the ownership.
* Implement the `Copy` trait on the type.

This can also happen when using a type implementing `Fn` or `FnMut`, as neither
allows moving out of them (they usually represent closures which can be called
more than once). Much of the text following applies equally well to non-`FnOnce`
closure bodies.

Examples:

```
Expand Down
27 changes: 20 additions & 7 deletions src/librustc_error_codes/error_codes/E0510.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
Cannot mutate place in this match guard.
The matched value was assigned in a match guard.

When matching on a variable it cannot be mutated in the match guards, as this
could cause the match to be non-exhaustive:
Erroneous code example:

```compile_fail,E0510
let mut x = Some(0);
match x {
None => (),
Some(_) if { x = None; false } => (),
Some(v) => (), // No longer matches
None => {}
Some(_) if { x = None; false } => {} // error!
Some(_) => {}
}
```

When matching on a variable it cannot be mutated in the match guards, as this
could cause the match to be non-exhaustive.

Here executing `x = None` would modify the value being matched and require us
to go "back in time" to the `None` arm.
to go "back in time" to the `None` arm. To fix it, change the value in the match
arm:

```
let mut x = Some(0);
match x {
None => {}
Some(_) => {
x = None; // ok!
}
}
```
26 changes: 23 additions & 3 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,19 @@ impl From<UnusedDelimsCtx> for &'static str {
trait UnusedDelimLint {
const DELIM_STR: &'static str;

/// Due to `ref` pattern, there can be a difference between using
/// `{ expr }` and `expr` in pattern-matching contexts. This means
/// that we should only lint `unused_parens` and not `unused_braces`
/// in this case.
///
/// ```rust
/// let mut a = 7;
/// let ref b = { a }; // We actually borrow a copy of `a` here.
/// a += 1; // By mutating `a` we invalidate any borrows of `a`.
/// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
/// ```
const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;

// this cannot be a constant is it refers to a static.
fn lint(&self) -> &'static Lint;

Expand Down Expand Up @@ -454,7 +467,10 @@ trait UnusedDelimLint {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
use rustc_ast::ast::ExprKind::*;
let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
If(ref cond, ref block, ..) => {
// Do not lint `unused_braces` in `if let` expressions.
If(ref cond, ref block, ..)
if !matches!(cond.kind, Let(_, _)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
{
let left = e.span.lo() + rustc_span::BytePos(2);
let right = block.span.lo();
(cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
Expand All @@ -470,7 +486,7 @@ trait UnusedDelimLint {
(cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
}

Match(ref head, _) => {
Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
let left = e.span.lo() + rustc_span::BytePos(5);
(head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
}
Expand Down Expand Up @@ -512,7 +528,7 @@ trait UnusedDelimLint {

fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
match s.kind {
StmtKind::Local(ref local) => {
StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
if let Some(ref value) = local.init {
self.check_unused_delims_expr(
cx,
Expand Down Expand Up @@ -565,6 +581,8 @@ declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
impl UnusedDelimLint for UnusedParens {
const DELIM_STR: &'static str = "parentheses";

const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;

fn lint(&self) -> &'static Lint {
UNUSED_PARENS
}
Expand Down Expand Up @@ -736,6 +754,8 @@ declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
impl UnusedDelimLint for UnusedBraces {
const DELIM_STR: &'static str = "braces";

const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;

fn lint(&self) -> &'static Lint {
UNUSED_BRACES
}
Expand Down
16 changes: 11 additions & 5 deletions src/librustc_middle/mir/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_index::vec::IndexVec;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec;
use std::iter;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::vec::IntoIter;

#[derive(Clone, Debug)]
pub struct Cache {
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
// Typically 95%+ of the inner vectors have 4 or fewer elements.
predecessors: Option<IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>>,
}

impl rustc_serialize::Encodable for Cache {
Expand Down Expand Up @@ -44,7 +46,7 @@ impl Cache {

pub fn ensure_predecessors(&mut self, body: &Body<'_>) {
if self.predecessors.is_none() {
let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
let mut result = IndexVec::from_elem(smallvec![], body.basic_blocks());
for (bb, data) in body.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors() {
Expand All @@ -58,7 +60,11 @@ impl Cache {
}

/// This will recompute the predecessors cache if it is not available
fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
// njn: typedef?
fn predecessors(
&mut self,
body: &Body<'_>,
) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.ensure_predecessors(body);
self.predecessors.as_ref().unwrap()
}
Expand Down Expand Up @@ -137,7 +143,7 @@ impl BodyAndCache<'tcx> {
self.cache.ensure_predecessors(&self.body);
}

pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.cache.predecessors(&self.body)
}

Expand Down Expand Up @@ -199,7 +205,7 @@ impl ReadOnlyBodyAndCache<'a, 'tcx> {
Self { body, cache }
}

pub fn predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
pub fn predecessors(&self) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.cache.predecessors.as_ref().unwrap()
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl FlagComputation {
}

fn add_flags(&mut self, flags: TypeFlags) {
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
self.flags = self.flags | flags;
}

/// indicates that `self` refers to something at binding level `binder`
Expand Down
Loading

0 comments on commit 485c5fb

Please sign in to comment.